diff --git a/README.md b/README.md index d66f1b0c..65b3f0e7 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Supported Algorithms lyra2h Hppcoin lyra2re lyra2 lyra2rev2 lyra2v2 - lyra2rev3 lyrav2v3, Vertcoin + lyra2rev3 lyrav2v3 lyra2z lyra2z330 Lyra2 330 rows, Zoin (ZOI) m7m Magi (XMG) @@ -122,6 +122,7 @@ Supported Algorithms tribus Denarius (DNR) vanilla blake256r8vnl (VCash) veltor (VLT) + verthash Vertcoin whirlpool whirlpoolx x11 Dash diff --git a/RELEASE_NOTES b/RELEASE_NOTES index e6c7f14a..1c7aca5e 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -65,6 +65,25 @@ If not what makes it happen or not happen? Change Log ---------- +v3.16.1 + +New options for verthash: + --data-file to specify the name, and optionally the path, of the verthash + data file, default is "verthash.dat" in the current directory. + --verify to perform the data file integrity check at startup, default is + not to verify data file integrity. + +Support for creation of default verthash data file if: + 1) --data-file option is not used, + 2) no default data file is found in the current directory, and, + 3) --verify option is used. + +More detailed logs related to verthash data file. + +Small verthash performance improvement. + +Fixed detection of corrupt stats caused by networking issues. + v3.16.0 Added verthash algo. diff --git a/algo-gate-api.c b/algo-gate-api.c index 2fea7afe..f34f5ac0 100644 --- a/algo-gate-api.c +++ b/algo-gate-api.c @@ -15,8 +15,6 @@ #include #include #include -#include -//#include "miner.h" #include "algo-gate-api.h" // Define null and standard functions. @@ -279,9 +277,11 @@ void init_algo_gate( algo_gate_t* gate ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wimplicit-function-declaration" -// called by each thread that uses the gate +// Called once by main bool register_algo_gate( int algo, algo_gate_t *gate ) { + bool rc = false; + if ( NULL == gate ) { applog(LOG_ERR,"FAIL: algo_gate registration failed, NULL gate\n"); @@ -290,109 +290,108 @@ bool register_algo_gate( int algo, algo_gate_t *gate ) init_algo_gate( gate ); - switch (algo) + switch ( algo ) { - case ALGO_ALLIUM: register_allium_algo ( gate ); break; - case ALGO_ANIME: register_anime_algo ( gate ); break; - case ALGO_ARGON2: register_argon2_algo ( gate ); break; - case ALGO_ARGON2D250: register_argon2d_crds_algo ( gate ); break; - case ALGO_ARGON2D500: register_argon2d_dyn_algo ( gate ); break; - case ALGO_ARGON2D4096: register_argon2d4096_algo ( gate ); break; - case ALGO_AXIOM: register_axiom_algo ( gate ); break; - case ALGO_BLAKE: register_blake_algo ( gate ); break; - case ALGO_BLAKE2B: register_blake2b_algo ( gate ); break; - case ALGO_BLAKE2S: register_blake2s_algo ( gate ); break; - case ALGO_BLAKECOIN: register_blakecoin_algo ( gate ); break; - case ALGO_BMW512: register_bmw512_algo ( gate ); break; - case ALGO_C11: register_c11_algo ( gate ); break; - case ALGO_DECRED: register_decred_algo ( gate ); break; - case ALGO_DEEP: register_deep_algo ( gate ); break; - case ALGO_DMD_GR: register_dmd_gr_algo ( gate ); break; - case ALGO_GROESTL: register_groestl_algo ( gate ); break; - case ALGO_HEX: register_hex_algo ( gate ); break; - case ALGO_HMQ1725: register_hmq1725_algo ( gate ); break; - case ALGO_HODL: register_hodl_algo ( gate ); break; - case ALGO_JHA: register_jha_algo ( gate ); break; - case ALGO_KECCAK: register_keccak_algo ( gate ); break; - case ALGO_KECCAKC: register_keccakc_algo ( gate ); break; - case ALGO_LBRY: register_lbry_algo ( gate ); break; - case ALGO_LYRA2H: register_lyra2h_algo ( gate ); break; - case ALGO_LYRA2RE: register_lyra2re_algo ( gate ); break; - case ALGO_LYRA2REV2: register_lyra2rev2_algo ( gate ); break; - case ALGO_LYRA2REV3: register_lyra2rev3_algo ( gate ); break; - case ALGO_LYRA2Z: register_lyra2z_algo ( gate ); break; - case ALGO_LYRA2Z330: register_lyra2z330_algo ( gate ); break; - case ALGO_M7M: register_m7m_algo ( gate ); break; - case ALGO_MINOTAUR: register_minotaur_algo ( gate ); break; - case ALGO_MYR_GR: register_myriad_algo ( gate ); break; - case ALGO_NEOSCRYPT: register_neoscrypt_algo ( gate ); break; - case ALGO_NIST5: register_nist5_algo ( gate ); break; - case ALGO_PENTABLAKE: register_pentablake_algo ( gate ); break; - case ALGO_PHI1612: register_phi1612_algo ( gate ); break; - case ALGO_PHI2: register_phi2_algo ( gate ); break; - case ALGO_POLYTIMOS: register_polytimos_algo ( gate ); break; - case ALGO_POWER2B: register_power2b_algo ( gate ); break; - case ALGO_QUARK: register_quark_algo ( gate ); break; - case ALGO_QUBIT: register_qubit_algo ( gate ); break; - case ALGO_SCRYPT: register_scrypt_algo ( gate ); break; - case ALGO_SHA256D: register_sha256d_algo ( gate ); break; - case ALGO_SHA256Q: register_sha256q_algo ( gate ); break; - case ALGO_SHA256T: register_sha256t_algo ( gate ); break; - case ALGO_SHA3D: register_sha3d_algo ( gate ); break; - case ALGO_SHAVITE3: register_shavite_algo ( gate ); break; - case ALGO_SKEIN: register_skein_algo ( gate ); break; - case ALGO_SKEIN2: register_skein2_algo ( gate ); break; - case ALGO_SKUNK: register_skunk_algo ( gate ); break; - case ALGO_SONOA: register_sonoa_algo ( gate ); break; - case ALGO_TIMETRAVEL: register_timetravel_algo ( gate ); break; - case ALGO_TIMETRAVEL10: register_timetravel10_algo ( gate ); break; - case ALGO_TRIBUS: register_tribus_algo ( gate ); break; - case ALGO_VANILLA: register_vanilla_algo ( gate ); break; - case ALGO_VELTOR: register_veltor_algo ( gate ); break; - case ALGO_VERTHASH: register_verthash_algo ( gate ); break; - case ALGO_WHIRLPOOL: register_whirlpool_algo ( gate ); break; - case ALGO_WHIRLPOOLX: register_whirlpoolx_algo ( gate ); break; - case ALGO_X11: register_x11_algo ( gate ); break; - case ALGO_X11EVO: register_x11evo_algo ( gate ); break; - case ALGO_X11GOST: register_x11gost_algo ( gate ); break; - case ALGO_X12: register_x12_algo ( gate ); break; - case ALGO_X13: register_x13_algo ( gate ); break; - case ALGO_X13BCD: register_x13bcd_algo ( gate ); break; - case ALGO_X13SM3: register_x13sm3_algo ( gate ); break; - case ALGO_X14: register_x14_algo ( gate ); break; - case ALGO_X15: register_x15_algo ( gate ); break; - case ALGO_X16R: register_x16r_algo ( gate ); break; - case ALGO_X16RV2: register_x16rv2_algo ( gate ); break; - case ALGO_X16RT: register_x16rt_algo ( gate ); break; - case ALGO_X16RT_VEIL: register_x16rt_veil_algo ( gate ); break; - case ALGO_X16S: register_x16s_algo ( gate ); break; - case ALGO_X17: register_x17_algo ( gate ); break; - case ALGO_X21S: register_x21s_algo ( gate ); break; - case ALGO_X22I: register_x22i_algo ( gate ); break; - case ALGO_X25X: register_x25x_algo ( gate ); break; - case ALGO_XEVAN: register_xevan_algo ( gate ); break; - case ALGO_YESCRYPT: register_yescrypt_05_algo ( gate ); break; + case ALGO_ALLIUM: rc = register_allium_algo ( gate ); break; + case ALGO_ANIME: rc = register_anime_algo ( gate ); break; + case ALGO_ARGON2: rc = register_argon2_algo ( gate ); break; + case ALGO_ARGON2D250: rc = register_argon2d_crds_algo ( gate ); break; + case ALGO_ARGON2D500: rc = register_argon2d_dyn_algo ( gate ); break; + case ALGO_ARGON2D4096: rc = register_argon2d4096_algo ( gate ); break; + case ALGO_AXIOM: rc = register_axiom_algo ( gate ); break; + case ALGO_BLAKE: rc = register_blake_algo ( gate ); break; + case ALGO_BLAKE2B: rc = register_blake2b_algo ( gate ); break; + case ALGO_BLAKE2S: rc = register_blake2s_algo ( gate ); break; + case ALGO_BLAKECOIN: rc = register_blakecoin_algo ( gate ); break; + case ALGO_BMW512: rc = register_bmw512_algo ( gate ); break; + case ALGO_C11: rc = register_c11_algo ( gate ); break; + case ALGO_DECRED: rc = register_decred_algo ( gate ); break; + case ALGO_DEEP: rc = register_deep_algo ( gate ); break; + case ALGO_DMD_GR: rc = register_dmd_gr_algo ( gate ); break; + case ALGO_GROESTL: rc = register_groestl_algo ( gate ); break; + case ALGO_HEX: rc = register_hex_algo ( gate ); break; + case ALGO_HMQ1725: rc = register_hmq1725_algo ( gate ); break; + case ALGO_HODL: rc = register_hodl_algo ( gate ); break; + case ALGO_JHA: rc = register_jha_algo ( gate ); break; + case ALGO_KECCAK: rc = register_keccak_algo ( gate ); break; + case ALGO_KECCAKC: rc = register_keccakc_algo ( gate ); break; + case ALGO_LBRY: rc = register_lbry_algo ( gate ); break; + case ALGO_LYRA2H: rc = register_lyra2h_algo ( gate ); break; + case ALGO_LYRA2RE: rc = register_lyra2re_algo ( gate ); break; + case ALGO_LYRA2REV2: rc = register_lyra2rev2_algo ( gate ); break; + case ALGO_LYRA2REV3: rc = register_lyra2rev3_algo ( gate ); break; + case ALGO_LYRA2Z: rc = register_lyra2z_algo ( gate ); break; + case ALGO_LYRA2Z330: rc = register_lyra2z330_algo ( gate ); break; + case ALGO_M7M: rc = register_m7m_algo ( gate ); break; + case ALGO_MINOTAUR: rc = register_minotaur_algo ( gate ); break; + case ALGO_MYR_GR: rc = register_myriad_algo ( gate ); break; + case ALGO_NEOSCRYPT: rc = register_neoscrypt_algo ( gate ); break; + case ALGO_NIST5: rc = register_nist5_algo ( gate ); break; + case ALGO_PENTABLAKE: rc = register_pentablake_algo ( gate ); break; + case ALGO_PHI1612: rc = register_phi1612_algo ( gate ); break; + case ALGO_PHI2: rc = register_phi2_algo ( gate ); break; + case ALGO_POLYTIMOS: rc = register_polytimos_algo ( gate ); break; + case ALGO_POWER2B: rc = register_power2b_algo ( gate ); break; + case ALGO_QUARK: rc = register_quark_algo ( gate ); break; + case ALGO_QUBIT: rc = register_qubit_algo ( gate ); break; + case ALGO_SCRYPT: rc = register_scrypt_algo ( gate ); break; + case ALGO_SHA256D: rc = register_sha256d_algo ( gate ); break; + case ALGO_SHA256Q: rc = register_sha256q_algo ( gate ); break; + case ALGO_SHA256T: rc = register_sha256t_algo ( gate ); break; + case ALGO_SHA3D: rc = register_sha3d_algo ( gate ); break; + case ALGO_SHAVITE3: rc = register_shavite_algo ( gate ); break; + case ALGO_SKEIN: rc = register_skein_algo ( gate ); break; + case ALGO_SKEIN2: rc = register_skein2_algo ( gate ); break; + case ALGO_SKUNK: rc = register_skunk_algo ( gate ); break; + case ALGO_SONOA: rc = register_sonoa_algo ( gate ); break; + case ALGO_TIMETRAVEL: rc = register_timetravel_algo ( gate ); break; + case ALGO_TIMETRAVEL10: rc = register_timetravel10_algo ( gate ); break; + case ALGO_TRIBUS: rc = register_tribus_algo ( gate ); break; + case ALGO_VANILLA: rc = register_vanilla_algo ( gate ); break; + case ALGO_VELTOR: rc = register_veltor_algo ( gate ); break; + case ALGO_VERTHASH: rc = register_verthash_algo ( gate ); break; + case ALGO_WHIRLPOOL: rc = register_whirlpool_algo ( gate ); break; + case ALGO_WHIRLPOOLX: rc = register_whirlpoolx_algo ( gate ); break; + case ALGO_X11: rc = register_x11_algo ( gate ); break; + case ALGO_X11EVO: rc = register_x11evo_algo ( gate ); break; + case ALGO_X11GOST: rc = register_x11gost_algo ( gate ); break; + case ALGO_X12: rc = register_x12_algo ( gate ); break; + case ALGO_X13: rc = register_x13_algo ( gate ); break; + case ALGO_X13BCD: rc = register_x13bcd_algo ( gate ); break; + case ALGO_X13SM3: rc = register_x13sm3_algo ( gate ); break; + case ALGO_X14: rc = register_x14_algo ( gate ); break; + case ALGO_X15: rc = register_x15_algo ( gate ); break; + case ALGO_X16R: rc = register_x16r_algo ( gate ); break; + case ALGO_X16RV2: rc = register_x16rv2_algo ( gate ); break; + case ALGO_X16RT: rc = register_x16rt_algo ( gate ); break; + case ALGO_X16RT_VEIL: rc = register_x16rt_veil_algo ( gate ); break; + case ALGO_X16S: rc = register_x16s_algo ( gate ); break; + case ALGO_X17: rc = register_x17_algo ( gate ); break; + case ALGO_X21S: rc = register_x21s_algo ( gate ); break; + case ALGO_X22I: rc = register_x22i_algo ( gate ); break; + case ALGO_X25X: rc = register_x25x_algo ( gate ); break; + case ALGO_XEVAN: rc = register_xevan_algo ( gate ); break; + case ALGO_YESCRYPT: rc = register_yescrypt_05_algo ( gate ); break; // case ALGO_YESCRYPT: register_yescrypt_algo ( gate ); break; - case ALGO_YESCRYPTR8: register_yescryptr8_05_algo ( gate ); break; + case ALGO_YESCRYPTR8: rc = register_yescryptr8_05_algo ( gate ); break; // case ALGO_YESCRYPTR8: register_yescryptr8_algo ( gate ); break; - case ALGO_YESCRYPTR8G: register_yescryptr8g_algo ( gate ); break; - case ALGO_YESCRYPTR16: register_yescryptr16_05_algo( gate ); break; + case ALGO_YESCRYPTR8G: rc = register_yescryptr8g_algo ( gate ); break; + case ALGO_YESCRYPTR16: rc = register_yescryptr16_05_algo( gate ); break; // case ALGO_YESCRYPTR16: register_yescryptr16_algo ( gate ); break; - case ALGO_YESCRYPTR32: register_yescryptr32_05_algo( gate ); break; + case ALGO_YESCRYPTR32: rc = register_yescryptr32_05_algo( gate ); break; // case ALGO_YESCRYPTR32: register_yescryptr32_algo ( gate ); break; - case ALGO_YESPOWER: register_yespower_algo ( gate ); break; - case ALGO_YESPOWERR16: register_yespowerr16_algo ( gate ); break; - case ALGO_YESPOWER_B2B: register_yespower_b2b_algo ( gate ); break; - case ALGO_ZR5: register_zr5_algo ( gate ); break; + case ALGO_YESPOWER: rc = register_yespower_algo ( gate ); break; + case ALGO_YESPOWERR16: rc = register_yespowerr16_algo ( gate ); break; + case ALGO_YESPOWER_B2B: rc = register_yespower_b2b_algo ( gate ); break; + case ALGO_ZR5: rc = register_zr5_algo ( gate ); break; default: - applog(LOG_ERR,"FAIL: algo_gate registration failed, unknown algo %s.\n", algo_names[opt_algo] ); + applog(LOG_ERR,"BUG: unregistered algorithm %s.\n", algo_names[opt_algo] ); return false; } // switch - // ensure required functions were defined. - if ( gate->scanhash == (void*)&null_scanhash ) + if ( !rc ) { - applog(LOG_ERR, "FAIL: Required algo_gate functions undefined\n"); + applog(LOG_ERR, "FAIL: %s algorithm failed to initialize\n", algo_names[opt_algo] ); return false; } return true; @@ -434,7 +433,6 @@ const char* const algo_alias_map[][2] = { "flax", "c11" }, { "hsr", "x13sm3" }, { "jackpot", "jha" }, - { "jane", "scryptjane" }, { "lyra2", "lyra2re" }, { "lyra2v2", "lyra2rev2" }, { "lyra2v3", "lyra2rev3" }, diff --git a/algo-gate-api.h b/algo-gate-api.h index c578f85a..8d61d266 100644 --- a/algo-gate-api.h +++ b/algo-gate-api.h @@ -114,15 +114,15 @@ typedef struct // Mandatory functions, one of these is mandatory. If a generic scanhash // is used a custom target hash function must be registered, with a custom // scanhash the target hash function can be called directly and doesn't need -// to be registered in the gate. +// to be registered with the gate. int ( *scanhash ) ( struct work*, uint32_t, uint64_t*, struct thr_info* ); int ( *hash ) ( void*, const void*, int ); //optional, safe to use default in most cases -// Allocate thread local buffers and other initialization specific to miner -// threads. +// Called once by each miner thread to allocate thread local buffers and +// other initialization specific to miner threads. bool ( *miner_thread_init ) ( int ); // Get thread local copy of blockheader with unique nonce. @@ -150,7 +150,7 @@ void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* ); char* ( *malloc_txs_request ) ( struct work* ); -// Big or little +// Big endian or little endian void ( *set_work_data_endian ) ( struct work* ); double ( *calc_network_diff ) ( struct work* ); @@ -260,7 +260,7 @@ int scanhash_8way_64in_32out( struct work *work, uint32_t max_nonce, #endif // displays warning -int null_hash (); +int null_hash(); // optional safe targets, default listed first unless noted. @@ -281,7 +281,7 @@ void std_be_build_stratum_request( char *req, struct work *work ); char* std_malloc_txs_request( struct work *work ); -// Default is do_nothing (assumed LE) +// Default is do_nothing, little endian is assumed void set_work_data_big_endian( struct work *work ); double std_calc_network_diff( struct work *work ); diff --git a/algo/verthash/.verthash-gate.c.swp b/algo/verthash/.verthash-gate.c.swp deleted file mode 100644 index 4c59aa9e..00000000 Binary files a/algo/verthash/.verthash-gate.c.swp and /dev/null differ diff --git a/algo/verthash/Verthash.c b/algo/verthash/Verthash.c index 5baeb68f..072df372 100644 --- a/algo/verthash/Verthash.c +++ b/algo/verthash/Verthash.c @@ -7,7 +7,9 @@ * any later version. See LICENSE for more details. */ +#include "algo-gate-api.h" #include "Verthash.h" +#include "mm_malloc.h" //----------------------------------------------------------------------------- // Verthash info management @@ -18,34 +20,71 @@ int verthash_info_init(verthash_info_t* info, const char* file_name) info->data = NULL; info->dataSize = 0; info->bitmask = 0; + size_t fileNameLen; - // get name - if (file_name == NULL) { return 1; } - size_t fileNameLen = strlen(file_name); - if (fileNameLen == 0) { return 1; } - - info->fileName = (char*)malloc(fileNameLen+1); - if (!info->fileName) + if ( !file_name || !( fileNameLen = strlen( file_name ) ) ) + { + applog( LOG_ERR, "Invalid file specification" ); + return -1; + } + + info->fileName = (char*)malloc( fileNameLen + 1 ); + if ( !info->fileName ) { - // Memory allocation fatal error. - return 2; + applog( LOG_ERR, "Failed to allocate memory for Verthash data" ); + return -1; } - memset(info->fileName, 0, fileNameLen+1); - memcpy(info->fileName, file_name, fileNameLen); + memset( info->fileName, 0, fileNameLen + 1 ); + memcpy( info->fileName, file_name, fileNameLen ); - // Load data - FILE *fileMiningData = fopen_utf8(info->fileName, "rb"); - // Failed to open file for reading - if (!fileMiningData) { return 1; } + FILE *fileMiningData = fopen_utf8( info->fileName, "rb" ); + if ( !fileMiningData ) + { + if ( opt_data_file || !opt_verify ) + { + if ( opt_data_file ) + applog( LOG_ERR, + "Verthash data file not found or invalid: %s", info->fileName ); + else + { + applog( LOG_ERR, + "No Verthash data file specified and default not found"); + applog( LOG_NOTICE, + "Add '--verify' to create default 'verthash.dat'"); + } + return -1; + } + else + { + applog( LOG_NOTICE, "Creating default 'verthash.dat' in current directory, this will take several minutes"); + if ( verthash_generate_data_file( info->fileName ) ) + return -1; + + fileMiningData = fopen_utf8( info->fileName, "rb" ); + if ( !fileMiningData ) + { + applog( LOG_ERR, "File system error opening %s", info->fileName ); + return -1; + } + + applog( LOG_NOTICE, "Verthash data file created successfully" ); + } + } // Get file size fseek(fileMiningData, 0, SEEK_END); - uint64_t fileSize = (uint64_t)ftell(fileMiningData); + int fileSize = ftell(fileMiningData); fseek(fileMiningData, 0, SEEK_SET); + if ( fileSize < 0 ) + { + fclose(fileMiningData); + return 1; + } + // Allocate data - info->data = (uint8_t *)malloc(fileSize); + info->data = (uint8_t *)_mm_malloc( fileSize, 64 ); if (!info->data) { fclose(fileMiningData); @@ -54,13 +93,20 @@ int verthash_info_init(verthash_info_t* info, const char* file_name) } // Load data - fread(info->data, fileSize, 1, fileMiningData); + if ( !fread( info->data, fileSize, 1, fileMiningData ) ) + { + applog( LOG_ERR, "File system error reading %s", info->fileName ); + fclose(fileMiningData); + return -1; + } + fclose(fileMiningData); // Update fields info->bitmask = ((fileSize - VH_HASH_OUT_SIZE)/VH_BYTE_ALIGNMENT) + 1; info->dataSize = fileSize; + applog( LOG_NOTICE, "Using Verthash data file '%s'", info->fileName ); return 0; } @@ -83,20 +129,6 @@ void verthash_info_free(verthash_info_t* info) #define VH_N_INDEXES 4096 #define VH_BYTE_ALIGNMENT 16 -static __thread sha3_ctx_t sha3_midstate_ctx; - -void verthash_sha3_prehash_72( const void *data ) -{ - sha3_init( &sha3_midstate_ctx, 256 ); - sha3_update( &sha3_midstate_ctx, data, 72 ); -} - -void verthash_sha3_final_8( sha3_ctx_t *ctx, void *out, const void *data ) -{ - sha3_update( ctx, data, 8 ); - sha3_final( out, ctx ); -} - static inline uint32_t fnv1a(const uint32_t a, const uint32_t b) { return (a ^ b) * 0x1000193; @@ -107,16 +139,12 @@ void verthash_hash(const unsigned char* blob_bytes, const unsigned char(*input)[VH_HEADER_SIZE], unsigned char(*output)[VH_HASH_OUT_SIZE]) { - unsigned char p1[VH_HASH_OUT_SIZE]; -// sha3_ctx_t sha3_ctx; -// memcpy ( &sha3_ctx, &sha3_midstate_ctx, sizeof sha3_ctx ); -// verthash_sha3_final_8( &sha3_ctx, &p1[0], &input[72] ); - + unsigned char p1[VH_HASH_OUT_SIZE] __attribute__ ((aligned (64))); sha3(&input[0], VH_HEADER_SIZE, &p1[0], VH_HASH_OUT_SIZE); unsigned char p0[VH_N_SUBSET]; - unsigned char input_header[VH_HEADER_SIZE]; + unsigned char input_header[VH_HEADER_SIZE] __attribute__ ((aligned (64))); memcpy(input_header, input, VH_HEADER_SIZE); for (size_t i = 0; i < VH_N_ITER; ++i) @@ -126,17 +154,47 @@ void verthash_hash(const unsigned char* blob_bytes, } uint32_t* p0_index = (uint32_t*)p0; - uint32_t seek_indexes[VH_N_INDEXES]; + uint32_t seek_indexes[VH_N_INDEXES] __attribute__ ((aligned (64))); - for (size_t x = 0; x < VH_N_ROT; ++x) + for ( size_t x = 0; x < VH_N_ROT; ++x ) { memcpy( seek_indexes + x * (VH_N_SUBSET / sizeof(uint32_t)), p0, VH_N_SUBSET); - for (size_t y = 0; y < VH_N_SUBSET / sizeof(uint32_t); ++y) + +//#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__) +// 512 bit vector processing is actually slower because it reduces the CPU +// clock significantly, which also slows mem access. The AVX512 rol instruction +// is still available for smaller vectors. + +// for ( size_t y = 0; y < VH_N_SUBSET / sizeof(uint32_t); y += 16 ) +// { +// __m512i *p0_v = (__m512i*)( p0_index + y ); +// *p0_v = mm512_rol_32( *p0_v, 1 ); +// } + +#if defined(__AVX2__) + + for ( size_t y = 0; y < VH_N_SUBSET / sizeof(uint32_t); y += 8 ) { - *(p0_index + y) = ( *(p0_index + y) << 1 ) - | ( 1 & (*(p0_index + y) >> 31) ); + __m256i *p0_v = (__m256i*)( p0_index + y ); + *p0_v = mm256_rol_32( *p0_v, 1 ); } + +#else + + for ( size_t y = 0; y < VH_N_SUBSET / sizeof(uint32_t); y += 4 ) + { + __m128i *p0_v = (__m128i*)( p0_index + y ); + *p0_v = mm128_rol_32( *p0_v, 1 ); + } + +#endif + +// for (size_t y = 0; y < VH_N_SUBSET / sizeof(uint32_t); ++y) +// { +// *(p0_index + y) = ( *(p0_index + y) << 1 ) +// | ( 1 & (*(p0_index + y) >> 31) ); +// } } uint32_t* p1_32 = (uint32_t*)p1; @@ -146,13 +204,13 @@ void verthash_hash(const unsigned char* blob_bytes, for (size_t i = 0; i < VH_N_INDEXES; i++) { const uint32_t offset = (fnv1a(seek_indexes[i], value_accumulator) % mdiv) * VH_BYTE_ALIGNMENT / sizeof(uint32_t); + const uint32_t *blob_off = blob_bytes_32 + offset; for (size_t i2 = 0; i2 < VH_HASH_OUT_SIZE / sizeof(uint32_t); i2++) { - const uint32_t value = *(blob_bytes_32 + offset + i2); + const uint32_t value = *( blob_off + i2 ); uint32_t* p1_ptr = p1_32 + i2; - *p1_ptr = fnv1a(*p1_ptr, value); - - value_accumulator = fnv1a(value_accumulator, value); + *p1_ptr = fnv1a( *p1_ptr, value ); + value_accumulator = fnv1a( value_accumulator, value ); } } @@ -591,6 +649,9 @@ struct Graph *NewGraph(int64_t index, const char* targetFile, uint8_t *pk) int64_t pow2 = 1 << ((uint64_t)log2); struct Graph *g = (struct Graph *)malloc(sizeof(struct Graph)); + + if ( !g ) return NULL; + g->db = db; g->log2 = log2; g->pow2 = pow2; @@ -607,14 +668,27 @@ struct Graph *NewGraph(int64_t index, const char* targetFile, uint8_t *pk) } //----------------------------------------------------------------------------- + +// use info for _mm_malloc, then verify file int verthash_generate_data_file(const char* output_file_name) { const char *hashInput = "Verthash Proof-of-Space Datafile"; - uint8_t *pk = (uint8_t*)malloc(NODE_SIZE); - sha3(hashInput, 32, pk, NODE_SIZE); + uint8_t *pk = (uint8_t*)malloc( NODE_SIZE ); + + if ( !pk ) + { + applog( LOG_ERR, "Verthash data memory allocation failed"); + return -1; + } + + sha3( hashInput, 32, pk, NODE_SIZE ); int64_t index = 17; - NewGraph(index, output_file_name, pk); + if ( !NewGraph( index, output_file_name, pk ) ) + { + applog( LOG_ERR, "Verthash file creation failed"); + return -1; + } return 0; } diff --git a/algo/verthash/Verthash.h b/algo/verthash/Verthash.h index 5eac0a4c..f81c9750 100644 --- a/algo/verthash/Verthash.h +++ b/algo/verthash/Verthash.h @@ -47,10 +47,6 @@ void verthash_info_free(verthash_info_t* info); //! Generate verthash data file and save it to specified location. int verthash_generate_data_file(const char* output_file_name); -void verthash_sha3_prehash_72( const void *data ); - -void verthash_sha3_final_8( sha3_ctx_t *ctx, void *out, const void *data ); - void verthash_hash(const unsigned char* blob_bytes, const size_t blob_size, const unsigned char(*input)[VH_HEADER_SIZE], diff --git a/algo/verthash/verthash-gate.c b/algo/verthash/verthash-gate.c index a3e0bc34..00c137fc 100644 --- a/algo/verthash/verthash-gate.c +++ b/algo/verthash/verthash-gate.c @@ -12,8 +12,6 @@ static const uint8_t verthashDatFileHash_bytes[32] = 0x29, 0xec, 0xf8, 0x8f, 0x8a, 0xd4, 0x76, 0x39, 0xb6, 0xed, 0xed, 0xaf, 0xd7, 0x21, 0xaa, 0x48 }; -static const char* verthash_data_file_name = "verthash.dat"; - int scanhash_verthash( struct work *work, uint32_t max_nonce, uint64_t *hashes_done, struct thr_info *mythr ) { @@ -28,7 +26,6 @@ int scanhash_verthash( struct work *work, uint32_t max_nonce, const bool bench = opt_benchmark; mm128_bswap32_80( edata, pdata ); -// verthash_sha3_prehash_72( edata ); do { edata[19] = n; @@ -47,6 +44,7 @@ int scanhash_verthash( struct work *work, uint32_t max_nonce, return 0; } +const char *default_verthash_data_file = "verthash.dat"; bool register_verthash_algo( algo_gate_t* gate ) { @@ -55,42 +53,49 @@ bool register_verthash_algo( algo_gate_t* gate ) gate->scanhash = (void*)&scanhash_verthash; // verthash data file - int vhLoadResult = verthash_info_init(&verthashInfo, verthash_data_file_name ); - // Check Verthash initialization status - if (vhLoadResult == 0) // No Error - { - applog(LOG_INFO, "Verthash data file has been loaded succesfully!"); - + char *verthash_data_file = opt_data_file ? opt_data_file + : default_verthash_data_file; + + int vhLoadResult = verthash_info_init( &verthashInfo, verthash_data_file ); + if (vhLoadResult == 0) // No Error + { // and verify data file(if it was enabled) - if ( true ) -// if (!cmdr.disableVerthashDataFileVerification) + if ( opt_verify ) { uint8_t vhDataFileHash[32] = { 0 }; + + applog( LOG_NOTICE, "Verifying Verthash data" ); sph_sha256_full( vhDataFileHash, verthashInfo.data, verthashInfo.dataSize ); - if ( memcmp( vhDataFileHash, verthashDatFileHash_bytes, sizeof(verthashDatFileHash_bytes) ) == 0 ) - applog(LOG_INFO, "Verthash data file has been verified succesfully!"); + applog( LOG_NOTICE, "Verthash data has been verified" ); else - applog(LOG_ERR, "Verthash data file verification has failed!"); + { + applog( LOG_ERR, "Verthash data verification has failed" ); + return false; + } } - else - applog(LOG_WARNING, "Verthash data file verification stage is disabled!"); } else + { - // Handle Verthash error codes - if (vhLoadResult == 1) - applog(LOG_ERR, "Verthash data file name is invalid"); - else if (vhLoadResult == 2) - applog(LOG_ERR, "Failed to allocate memory for Verthash data"); - else // for debugging purposes - applog(LOG_ERR, "Verthash data initialization unknown error code: %d", - vhLoadResult); - return false; + // Handle Verthash error codes + if ( vhLoadResult == 1 ) + { + applog( LOG_ERR, "Verthash data file not found: %s", verthash_data_file ); + if ( !opt_data_file ) + applog( LOG_NOTICE, "Add '--verify' to create verthash.dat"); + } + else if ( vhLoadResult == 2 ) + applog( LOG_ERR, "Failed to allocate memory for Verthash data" ); +// else // for debugging purposes +// applog( LOG_ERR, "Verthash data initialization unknown error code: %d", +// vhLoadResult ); + return false; } + printf("\n"); return true; } diff --git a/configure b/configure index b1b74084..00998223 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.15.8. +# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.16.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='cpuminer-opt' PACKAGE_TARNAME='cpuminer-opt' -PACKAGE_VERSION='3.15.8' -PACKAGE_STRING='cpuminer-opt 3.15.8' +PACKAGE_VERSION='3.16.1' +PACKAGE_STRING='cpuminer-opt 3.16.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1332,7 +1332,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures cpuminer-opt 3.15.8 to adapt to many kinds of systems. +\`configure' configures cpuminer-opt 3.16.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1404,7 +1404,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of cpuminer-opt 3.15.8:";; + short | recursive ) echo "Configuration of cpuminer-opt 3.16.1:";; esac cat <<\_ACEOF @@ -1509,7 +1509,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -cpuminer-opt configure 3.15.8 +cpuminer-opt configure 3.16.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2012,7 +2012,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by cpuminer-opt $as_me 3.15.8, which was +It was created by cpuminer-opt $as_me 3.16.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2993,7 +2993,7 @@ fi # Define the identity of the package. PACKAGE='cpuminer-opt' - VERSION='3.15.8' + VERSION='3.16.1' cat >>confdefs.h <<_ACEOF @@ -6690,7 +6690,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by cpuminer-opt $as_me 3.15.8, which was +This file was extended by cpuminer-opt $as_me 3.16.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6756,7 +6756,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -cpuminer-opt config.status 3.15.8 +cpuminer-opt config.status 3.16.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 3923c436..29b3b9a7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([cpuminer-opt], [3.16.0]) +AC_INIT([cpuminer-opt], [3.16.1]) AC_PREREQ([2.59c]) AC_CANONICAL_SYSTEM diff --git a/cpu-miner.c b/cpu-miner.c index 3b4839ed..0ed29b92 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -112,7 +112,6 @@ char* opt_param_key = NULL; int opt_param_n = 0; int opt_param_r = 0; int opt_n_threads = 0; -bool opt_reset_on_stale = false; bool opt_sapling = false; // Windows doesn't support 128 bit affinity mask. @@ -134,6 +133,8 @@ char *rpc_userpass = NULL; char *rpc_user, *rpc_pass; char *short_url = NULL; char *coinbase_address; +char *opt_data_file = NULL; +bool opt_verify = false; // pk_buffer_size is used as a version selector by b58 code, therefore // it must be set correctly to work. @@ -1070,12 +1071,11 @@ void report_summary_log( bool force ) double share_time = (double)et.tv_sec + (double)et.tv_usec / 1e6; double ghrate = global_hashrate; - double shrate = share_time == 0. ? 0. : exp32 * last_targetdiff - * (double)(accepts) / share_time; - double sess_hrate = uptime.tv_sec == 0. ? 0. : exp32 * norm_diff_sum - / (double)uptime.tv_sec; - double submit_rate = share_time == 0. ? 0. : (double)submits*60. - / share_time; + double shrate = safe_div( exp32 * last_targetdiff * (double)(accepts), + share_time, 0. ); + double sess_hrate = safe_div( exp32 * norm_diff_sum, + (double)uptime.tv_sec, 0. ); + double submit_rate = safe_div( (double)submits * 60., share_time, 0. ); char shr_units[4] = {0}; char ghr_units[4] = {0}; char sess_hr_units[4] = {0}; @@ -1092,11 +1092,10 @@ void report_summary_log( bool force ) applog( LOG_BLUE, "%s: %s", algo_names[ opt_algo ], short_url ); applog2( LOG_NOTICE, "Periodic Report %s %s", et_str, upt_str ); applog2( LOG_INFO, "Share rate %.2f/min %.2f/min", - submit_rate, (double)submitted_share_count*60. / - ( (double)uptime.tv_sec + (double)uptime.tv_usec / 1e6 ) ); + submit_rate, (double)submitted_share_count*60. / + ( (double)uptime.tv_sec + (double)uptime.tv_usec / 1e6 ) ); applog2( LOG_INFO, "Hash rate %7.2f%sh/s %7.2f%sh/s (%.2f%sh/s)", - shrate, shr_units, sess_hrate, sess_hr_units, - ghrate, ghr_units ); + shrate, shr_units, sess_hrate, sess_hr_units, ghrate, ghr_units ); if ( accepted_share_count < submitted_share_count ) { @@ -1110,37 +1109,40 @@ void report_summary_log( bool force ) char lghr_units[4] = {0}; scale_hash_for_display( &lost_shrate, lshr_units ); scale_hash_for_display( &lost_ghrate, lghr_units ); - applog2( LOG_INFO, "Lost hash rate %7.2f%sh/s %7.2f%sh/s", - lost_shrate, lshr_units, lost_ghrate, lghr_units ); + applog2( LOG_INFO, "Lost hash rate %7.2f%sh/s %7.2f%sh/s", + lost_shrate, lshr_units, lost_ghrate, lghr_units ); } - applog2( LOG_INFO,"Submitted %6d %6d", - submits, submitted_share_count ); - applog2( LOG_INFO,"Accepted %6d %6d %5.1f%%", - accepts, accepted_share_count, - 100. * accepted_share_count / submitted_share_count ); + applog2( LOG_INFO,"Submitted %7d %7d", + submits, submitted_share_count ); + applog2( LOG_INFO, "Accepted %7d %7d %5.1f%%", + accepts, accepted_share_count, + 100. * safe_div( (double)accepted_share_count, + (double)submitted_share_count, 0. ) ); if ( stale_share_count ) - applog2( LOG_INFO,"Stale %6d %6d %5.1f%%", - stales, stale_share_count, - 100. * stale_share_count / submitted_share_count ); + applog2( LOG_INFO, "Stale %7d %7d %5.1f%%", + stales, stale_share_count, + 100. * safe_div( (double)stale_share_count, + (double)submitted_share_count, 0. ) ); if ( rejected_share_count ) - applog2( LOG_INFO,"Rejected %6d %6d %5.1f%%", - rejects, rejected_share_count, - 100. * rejected_share_count / submitted_share_count ); + applog2( LOG_INFO, "Rejected %7d %7d %5.1f%%", + rejects, rejected_share_count, + 100. * safe_div( (double)rejected_share_count, + (double)submitted_share_count, 0. ) ); if ( solved_block_count ) - applog2( LOG_INFO,"Blocks Solved %6d %6d", - solved, solved_block_count ); + applog2( LOG_INFO,"Blocks Solved %7d %7d", + solved, solved_block_count ); applog2( LOG_INFO, "Hi/Lo Share Diff %.5g / %.5g", - highest_share, lowest_share ); + highest_share, lowest_share ); - static int64_t no_acks = 0; - if ( no_acks ) - { - no_acks = submitted_share_count + int mismatch = submitted_share_count - ( accepted_share_count + stale_share_count + rejected_share_count ); - if ( no_acks ) // 2 consecutive cycles non zero - applog(LOG_WARNING,"Share count mismatch: %d, stats may be incorrect", - no_acks ); + if ( mismatch ) + { + if ( mismatch != 1 ) + applog(LOG_WARNING,"Share count mismatch: %d, stats may be incorrect", mismatch ); + else + applog(LOG_INFO,"Share count mismatch, submitted share may still be pending" ); } } @@ -1294,7 +1296,8 @@ static int share_result( int result, struct work *work, if ( reason ) applog( LOG_WARNING, "Reject reason: %s", reason ); diff_to_hash( str, my_stats.share_diff ); - applog2( LOG_INFO, "Hash: %08x%08x%08x...", str[7], str[6], str[5] ); + applog2( LOG_INFO, "Hash: %08x%08x%08x%08x%08x%08x", str[7], str[6], + str[5], str[4], str[3],str[2], str[1], str[0] ); if ( work ) targ = work->target; @@ -1303,7 +1306,8 @@ static int share_result( int result, struct work *work, diff_to_hash( str, my_stats.target_diff ); targ = &str[0]; } - applog2( LOG_INFO, "Target: %08x%08x%08x...", targ[7], targ[6], targ[5] ); + applog2( LOG_INFO, "Target: %08x%08x%08x%08x%08x%08x", targ[7], targ[6], + targ[5], targ[4], targ[3], targ[2], targ[1], targ[0] ); } return 1; } @@ -2790,6 +2794,189 @@ static void *stratum_thread(void *userdata ) return NULL; } +static void show_credits() +{ + printf("\n ********** "PACKAGE_NAME" "PACKAGE_VERSION" *********** \n"); + printf(" A CPU miner with multi algo support and optimized for CPUs\n"); + printf(" with AVX512, SHA and VAES extensions by JayDDee.\n"); + printf(" BTC donation address: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT\n\n"); +} + +#define check_cpu_capability() cpu_capability( false ) +#define display_cpu_capability() cpu_capability( true ) +static bool cpu_capability( bool display_only ) +{ + char cpu_brand[0x40]; + bool cpu_has_sse2 = has_sse2(); + bool cpu_has_aes = has_aes_ni(); + bool cpu_has_sse42 = has_sse42(); + bool cpu_has_avx = has_avx(); + bool cpu_has_avx2 = has_avx2(); + bool cpu_has_sha = has_sha(); + bool cpu_has_avx512 = has_avx512(); + bool cpu_has_vaes = has_vaes(); + bool sw_has_aes = false; + bool sw_has_sse2 = false; + bool sw_has_sse42 = false; + bool sw_has_avx = false; + bool sw_has_avx2 = false; + bool sw_has_avx512 = false; + bool sw_has_sha = false; + bool sw_has_vaes = false; + set_t algo_features = algo_gate.optimizations; + bool algo_has_sse2 = set_incl( SSE2_OPT, algo_features ); + bool algo_has_aes = set_incl( AES_OPT, algo_features ); + bool algo_has_sse42 = set_incl( SSE42_OPT, algo_features ); + bool algo_has_avx2 = set_incl( AVX2_OPT, algo_features ); + bool algo_has_avx512 = set_incl( AVX512_OPT, algo_features ); + bool algo_has_sha = set_incl( SHA_OPT, algo_features ); + bool algo_has_vaes = set_incl( VAES_OPT, algo_features ); + bool algo_has_vaes256 = set_incl( VAES256_OPT, algo_features ); + bool use_aes; + bool use_sse2; + bool use_sse42; + bool use_avx2; + bool use_avx512; + bool use_sha; + bool use_vaes; + bool use_none; + + #ifdef __AES__ + sw_has_aes = true; + #endif + #ifdef __SSE2__ + sw_has_sse2 = true; + #endif + #ifdef __SSE4_2__ + sw_has_sse42 = true; + #endif + #ifdef __AVX__ + sw_has_avx = true; + #endif + #ifdef __AVX2__ + sw_has_avx2 = true; + #endif + #if (defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512BW__) && defined(__AVX512VL__)) + sw_has_avx512 = true; + #endif + #ifdef __SHA__ + sw_has_sha = true; + #endif + #ifdef __VAES__ + sw_has_vaes = true; + #endif + + +// #if !((__AES__) || (__SSE2__)) +// printf("Neither __AES__ nor __SSE2__ defined.\n"); +// #endif + + cpu_brand_string( cpu_brand ); + printf( "CPU: %s\n", cpu_brand ); + + printf("SW built on " __DATE__ + #ifdef _MSC_VER + " with VC++ 2013\n"); + #elif defined(__GNUC__) + " with GCC"); + printf(" %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); + #else + printf("\n"); + #endif + + printf("CPU features: "); + if ( cpu_has_avx512 ) printf( " AVX512" ); + else if ( cpu_has_avx2 ) printf( " AVX2 " ); + else if ( cpu_has_avx ) printf( " AVX " ); + else if ( cpu_has_sse42 ) printf( " SSE4.2" ); + else if ( cpu_has_sse2 ) printf( " SSE2 " ); + if ( cpu_has_vaes ) printf( " VAES" ); + else if ( cpu_has_aes ) printf( " AES" ); + if ( cpu_has_sha ) printf( " SHA" ); + + printf("\nSW features: "); + if ( sw_has_avx512 ) printf( " AVX512" ); + else if ( sw_has_avx2 ) printf( " AVX2 " ); + else if ( sw_has_avx ) printf( " AVX " ); + else if ( sw_has_sse42 ) printf( " SSE4.2" ); + else if ( sw_has_sse2 ) printf( " SSE2 " ); + if ( sw_has_vaes ) printf( " VAES" ); + else if ( sw_has_aes ) printf( " AES" ); + if ( sw_has_sha ) printf( " SHA" ); + + printf("\nAlgo features:"); + if ( algo_features == EMPTY_SET ) printf( " None" ); + else + { + if ( algo_has_avx512 ) printf( " AVX512" ); + else if ( algo_has_avx2 ) printf( " AVX2 " ); + else if ( algo_has_sse42 ) printf( " SSE4.2" ); + else if ( algo_has_sse2 ) printf( " SSE2 " ); + if ( algo_has_vaes ) printf( " VAES" ); + else if ( algo_has_aes ) printf( " AES" ); + if ( algo_has_sha ) printf( " SHA" ); + } + printf("\n"); + + if ( display_only ) return true; + + // Check for CPU and build incompatibilities + if ( !cpu_has_sse2 ) + { + printf( "A CPU with SSE2 is required to use cpuminer-opt\n" ); + return false; + } + if ( sw_has_avx2 && !( cpu_has_avx2 && cpu_has_aes ) ) + { + printf( "The SW build requires a CPU with AES and AVX2!\n" ); + return false; + } + if ( sw_has_sse42 && !cpu_has_sse42 ) + { + printf( "The SW build requires a CPU with SSE4.2!\n" ); + return false; + } + if ( sw_has_aes && !cpu_has_aes ) + { + printf( "The SW build requires a CPU with AES!\n" ); + return false; + } + if ( sw_has_sha && !cpu_has_sha ) + { + printf( "The SW build requires a CPU with SHA!\n" ); + return false; + } + + // Determine mining options + use_sse2 = cpu_has_sse2 && algo_has_sse2; + use_aes = cpu_has_aes && sw_has_aes && algo_has_aes; + use_sse42 = cpu_has_sse42 && sw_has_sse42 && algo_has_sse42; + use_avx2 = cpu_has_avx2 && sw_has_avx2 && algo_has_avx2; + use_avx512 = cpu_has_avx512 && sw_has_avx512 && algo_has_avx512; + use_sha = cpu_has_sha && sw_has_sha && algo_has_sha; + use_vaes = cpu_has_vaes && sw_has_vaes && algo_has_vaes + && ( use_avx512 || algo_has_vaes256 ); + use_none = !( use_sse2 || use_aes || use_sse42 || use_avx512 || use_avx2 || + use_sha || use_vaes ); + + // Display best options + printf( "\nStarting miner with" ); + if ( use_none ) printf( " no optimizations" ); + else + { + if ( use_avx512 ) printf( " AVX512" ); + else if ( use_avx2 ) printf( " AVX2" ); + else if ( use_sse42 ) printf( " SSE4.2" ); + else if ( use_sse2 ) printf( " SSE2" ); + if ( use_vaes ) printf( " VAES" ); + else if ( use_aes ) printf( " AES" ); + if ( use_sha ) printf( " SHA" ); + } + printf( "...\n\n" ); + + return true; +} + void show_version_and_exit(void) { printf("\n built on " __DATE__ @@ -2837,7 +3024,6 @@ void show_version_and_exit(void) #endif "\n\n"); - /* dependencies versions */ printf("%s\n", curl_version()); #ifdef JANSSON_VERSION printf("jansson/%s ", JANSSON_VERSION); @@ -2849,7 +3035,6 @@ void show_version_and_exit(void) exit(0); } - void show_usage_and_exit(int status) { if (status) @@ -3237,11 +3422,15 @@ void parse_arg(int key, char *arg ) case 1024: opt_randomize = true; break; - case 1026: - opt_reset_on_stale = true; + case 1027: // data-file + opt_data_file = strdup( arg ); + break; + case 1028: // verify + opt_verify = true; break; case 'V': - show_version_and_exit(); + display_cpu_capability(); + exit(0); case 'h': show_usage_and_exit(0); @@ -3358,185 +3547,6 @@ static int thread_create(struct thr_info *thr, void* func) return err; } -static void show_credits() -{ - printf("\n ********** "PACKAGE_NAME" "PACKAGE_VERSION" *********** \n"); - printf(" A CPU miner with multi algo support and optimized for CPUs\n"); - printf(" with AVX512, SHA and VAES extensions by JayDDee.\n"); - printf(" BTC donation address: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT\n\n"); -} - -bool check_cpu_capability () -{ - char cpu_brand[0x40]; - bool cpu_has_sse2 = has_sse2(); - bool cpu_has_aes = has_aes_ni(); - bool cpu_has_sse42 = has_sse42(); - bool cpu_has_avx = has_avx(); - bool cpu_has_avx2 = has_avx2(); - bool cpu_has_sha = has_sha(); - bool cpu_has_avx512 = has_avx512(); - bool cpu_has_vaes = has_vaes(); - bool sw_has_aes = false; - bool sw_has_sse2 = false; - bool sw_has_sse42 = false; - bool sw_has_avx = false; - bool sw_has_avx2 = false; - bool sw_has_avx512 = false; - bool sw_has_sha = false; - bool sw_has_vaes = false; - set_t algo_features = algo_gate.optimizations; - bool algo_has_sse2 = set_incl( SSE2_OPT, algo_features ); - bool algo_has_aes = set_incl( AES_OPT, algo_features ); - bool algo_has_sse42 = set_incl( SSE42_OPT, algo_features ); - bool algo_has_avx2 = set_incl( AVX2_OPT, algo_features ); - bool algo_has_avx512 = set_incl( AVX512_OPT, algo_features ); - bool algo_has_sha = set_incl( SHA_OPT, algo_features ); - bool algo_has_vaes = set_incl( VAES_OPT, algo_features ); - bool algo_has_vaes256 = set_incl( VAES256_OPT, algo_features ); - bool use_aes; - bool use_sse2; - bool use_sse42; - bool use_avx2; - bool use_avx512; - bool use_sha; - bool use_vaes; - bool use_none; - - #ifdef __AES__ - sw_has_aes = true; - #endif - #ifdef __SSE2__ - sw_has_sse2 = true; - #endif - #ifdef __SSE4_2__ - sw_has_sse42 = true; - #endif - #ifdef __AVX__ - sw_has_avx = true; - #endif - #ifdef __AVX2__ - sw_has_avx2 = true; - #endif - #if (defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512BW__) && defined(__AVX512VL__)) - sw_has_avx512 = true; - #endif - #ifdef __SHA__ - sw_has_sha = true; - #endif - #ifdef __VAES__ - sw_has_vaes = true; - #endif - - -// #if !((__AES__) || (__SSE2__)) -// printf("Neither __AES__ nor __SSE2__ defined.\n"); -// #endif - - cpu_brand_string( cpu_brand ); - printf( "CPU: %s\n", cpu_brand ); - - printf("SW built on " __DATE__ - #ifdef _MSC_VER - " with VC++ 2013\n"); - #elif defined(__GNUC__) - " with GCC"); - printf(" %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); - #else - printf("\n"); - #endif - - printf("CPU features: "); - if ( cpu_has_avx512 ) printf( " AVX512" ); - else if ( cpu_has_avx2 ) printf( " AVX2 " ); - else if ( cpu_has_avx ) printf( " AVX " ); - else if ( cpu_has_sse42 ) printf( " SSE4.2" ); - else if ( cpu_has_sse2 ) printf( " SSE2 " ); - if ( cpu_has_vaes ) printf( " VAES" ); - else if ( cpu_has_aes ) printf( " AES" ); - if ( cpu_has_sha ) printf( " SHA" ); - - printf("\nSW features: "); - if ( sw_has_avx512 ) printf( " AVX512" ); - else if ( sw_has_avx2 ) printf( " AVX2 " ); - else if ( sw_has_avx ) printf( " AVX " ); - else if ( sw_has_sse42 ) printf( " SSE4.2" ); - else if ( sw_has_sse2 ) printf( " SSE2 " ); - if ( sw_has_vaes ) printf( " VAES" ); - else if ( sw_has_aes ) printf( " AES" ); - if ( sw_has_sha ) printf( " SHA" ); - - printf("\nAlgo features:"); - if ( algo_features == EMPTY_SET ) printf( " None" ); - else - { - if ( algo_has_avx512 ) printf( " AVX512" ); - else if ( algo_has_avx2 ) printf( " AVX2 " ); - else if ( algo_has_sse42 ) printf( " SSE4.2" ); - else if ( algo_has_sse2 ) printf( " SSE2 " ); - if ( algo_has_vaes ) printf( " VAES" ); - else if ( algo_has_aes ) printf( " AES" ); - if ( algo_has_sha ) printf( " SHA" ); - } - printf("\n"); - - // Check for CPU and build incompatibilities - if ( !cpu_has_sse2 ) - { - printf( "A CPU with SSE2 is required to use cpuminer-opt\n" ); - return false; - } - if ( sw_has_avx2 && !( cpu_has_avx2 && cpu_has_aes ) ) - { - printf( "The SW build requires a CPU with AES and AVX2!\n" ); - return false; - } - if ( sw_has_sse42 && !cpu_has_sse42 ) - { - printf( "The SW build requires a CPU with SSE4.2!\n" ); - return false; - } - if ( sw_has_aes && !cpu_has_aes ) - { - printf( "The SW build requires a CPU with AES!\n" ); - return false; - } - if ( sw_has_sha && !cpu_has_sha ) - { - printf( "The SW build requires a CPU with SHA!\n" ); - return false; - } - - // Determine mining options - use_sse2 = cpu_has_sse2 && algo_has_sse2; - use_aes = cpu_has_aes && sw_has_aes && algo_has_aes; - use_sse42 = cpu_has_sse42 && sw_has_sse42 && algo_has_sse42; - use_avx2 = cpu_has_avx2 && sw_has_avx2 && algo_has_avx2; - use_avx512 = cpu_has_avx512 && sw_has_avx512 && algo_has_avx512; - use_sha = cpu_has_sha && sw_has_sha && algo_has_sha; - use_vaes = cpu_has_vaes && sw_has_vaes && algo_has_vaes - && ( use_avx512 || algo_has_vaes256 ); - use_none = !( use_sse2 || use_aes || use_sse42 || use_avx512 || use_avx2 || - use_sha || use_vaes ); - - // Display best options - printf( "\nStarting miner with" ); - if ( use_none ) printf( " no optimizations" ); - else - { - if ( use_avx512 ) printf( " AVX512" ); - else if ( use_avx2 ) printf( " AVX2" ); - else if ( use_sse42 ) printf( " SSE4.2" ); - else if ( use_sse2 ) printf( " SSE2" ); - if ( use_vaes ) printf( " VAES" ); - else if ( use_aes ) printf( " AES" ); - if ( use_sha ) printf( " SHA" ); - } - printf( "...\n\n" ); - - return true; -} - void get_defconfig_path(char *out, size_t bufsize, char *argv0); int main(int argc, char *argv[]) @@ -3598,6 +3608,11 @@ int main(int argc, char *argv[]) fprintf(stderr, "%s: no algo supplied\n", argv[0]); show_usage_and_exit(1); } + + if ( !register_algo_gate( opt_algo, &algo_gate ) ) exit(1); + + if ( !check_cpu_capability() ) exit(1); + if ( !opt_benchmark ) { if ( !short_url ) @@ -3637,7 +3652,7 @@ int main(int argc, char *argv[]) } // All options must be set before starting the gate - if ( !register_algo_gate( opt_algo, &algo_gate ) ) exit(1); +// if ( !register_algo_gate( opt_algo, &algo_gate ) ) exit(1); if ( coinbase_address ) { @@ -3656,7 +3671,7 @@ int main(int argc, char *argv[]) memcpy( &five_min_start, &last_submit_time, sizeof (struct timeval) ); memcpy( &session_start, &last_submit_time, sizeof (struct timeval) ); - if ( !check_cpu_capability() ) exit(1); +// if ( !check_cpu_capability() ) exit(1); pthread_mutex_init( &stats_lock, NULL ); pthread_rwlock_init( &g_work_lock, NULL ); diff --git a/miner.h b/miner.h index e43012da..9e2749a3 100644 --- a/miner.h +++ b/miner.h @@ -737,7 +737,6 @@ extern uint32_t opt_work_size; extern double *thr_hashrates; extern double global_hashrate; extern double stratum_diff; -extern bool opt_reset_on_stale; extern double net_diff; extern double net_hashrate; extern int opt_param_n; @@ -762,6 +761,8 @@ extern pthread_mutex_t stats_lock; extern bool opt_sapling; extern const int pk_buffer_size_max; extern int pk_buffer_size; +extern char *opt_data_file; +extern bool opt_verify; static char const usage[] = "\ Usage: cpuminer [OPTIONS]\n\ @@ -905,6 +906,8 @@ Options:\n\ --max-rate=N[KMG] Only mine if net hashrate is less than specified value\n\ --max-diff=N Only mine if net difficulty is less than specified value\n\ -c, --config=FILE load a JSON-format configuration file\n\ + --data-file path and name of data file\n\ + --verify enable additional time consuming start up tests\n\ -V, --version display version information and exit\n\ -h, --help display this help text and exit\n\ "; @@ -962,7 +965,6 @@ static struct option const options[] = { { "retries", 1, NULL, 'r' }, { "retry-pause", 1, NULL, 1025 }, { "randomize", 0, NULL, 1024 }, - { "reset-on-stale", 0, NULL, 1026 }, { "scantime", 1, NULL, 's' }, #ifdef HAVE_SYSLOG_H { "syslog", 0, NULL, 'S' }, @@ -973,6 +975,8 @@ static struct option const options[] = { { "url", 1, NULL, 'o' }, { "user", 1, NULL, 'u' }, { "userpass", 1, NULL, 'O' }, + { "data-file", 1, NULL, 1027 }, + { "verify", 0, NULL, 1028 }, { "version", 0, NULL, 'V' }, { 0, 0, 0, 0 } }; diff --git a/simd-utils/simd-int.h b/simd-utils/simd-int.h index 5fff450f..4a7188e5 100644 --- a/simd-utils/simd-int.h +++ b/simd-utils/simd-int.h @@ -5,6 +5,10 @@ #define bswap_64( a ) __builtin_bswap64( a ) #define bswap_32( a ) __builtin_bswap32( a ) +// safe division, integer or floating point +#define safe_div( dividend, divisor, safe_result ) \ + ( (divisor) == 0 ? safe_result : ( (dividend) / (divisor) ) ) + /////////////////////////////////////// // diff --git a/verthash-help.txt b/verthash-help.txt index b055ec31..f8e02db4 100644 --- a/verthash-help.txt +++ b/verthash-help.txt @@ -1,17 +1,80 @@ +Quickstart: +---------- -The verthash data file must be named verthash.dat and located in the same -directory as the cpuminer executable. A Linux symlink works. +First time mining verthash or don't have a Verthash data file: -The verthash data file must be obtained seperately. If you already use -VerthashMiner you can simply copy or link the existing data file to the -cpuminer directory, using the required name. +--algo verthash --verify --url ... -Otherwise it may be created using -https://github.com/CryptoGraphics/VerthashMiner/releases -following the instructions. A GPU is not necessary to create the file. +Verthash data file already exists: -The same data file can be used by both cpuminer and VerthashMiner -simultaneously. +--algo verthash --data-file /path/to/verthash.dat --url ... + + +Background: +---------- + +Verthash algorithm requires a data file for hashing. This file is +static, portable, and only needs to be created once. + +A Verthash data file created by VerthashMiner can also be used by cpuminer-opt +and used simultaneously by both miners. + +Due to its size >1GB it is recommened one data file be created and +stored in a permanent location accessible to any miner that wants to use it. + +New command line options: +------------------------ + +cpuminer-opt adds two new command line options for verthash. The names +and some behaviour is changed from VerthashMiner. + +--data-file /path/to/verthash.dat + default when not used is verthash.dat in current working directory. + +--verify + verify integrity of file specified by --data-file, or if not specified + the default data file if it exists, or create a default file and verify it + if one does not yet exist. Data file verification is disabled by default. + +Detailed usage: +-------------- + +If a data file already exists it can be selected using the --data-file +option to specify the path and name of the file. + +--algo verthash --datafile /path/to/verthash.dat --url ... + +If the --data-file option is not used the default is to use 'verthash.dat' +from the current working directory. + +If no data file exists it can be created by using the --verify option +without the --data-file option. If the default data file is not found in +the current directory it will be created. + +--algo verthash --verify --url ... + +Data file creation can take up to 30 minutes on a spinning hard drive. +Once created the new data file will be verified and used immediately +if a valid url and user were included on the command line. + +A default data file can be created by ommitting the url option. That will +either verify an existing default data file or create one and verify it, +then exit. + +--algo verthash --verify + +A data file will never be created if --data-file is specified. The miner +will exit with an error if the file is not found. This is to avoid accidentally +creating an unwanted data file due to a typo. + +After creation the data file can moved to a more convenient location and +referenced by --data-file, or left where it is and used by default without the +--data-file option. + +Data file verification takes a few seconds and is disabled by default. +VerthashMiner enables data file verification by default and has an option to +disable it. + +The --verify option is intended primarily to create a new file. It's +not necessary or useful to verify a file every time the miner is started. -Launching cpuminer to mine verthash is the same as any other algorithm, -no extra options are required.