From 3022f19edad6c52222f9b3af9202296e296fd500 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 17 Aug 2019 01:42:03 +0700 Subject: [PATCH] Added selection for optimized Argon2 implementation. --- cmake/argon2.cmake | 7 ++- src/3rdparty/argon2/CMakeLists.txt | 83 +++++++++++++------------- src/3rdparty/argon2/include/argon2.h | 2 + src/3rdparty/argon2/lib/impl-select.c | 28 ++++++++- src/backend/cpu/CpuBackend.cpp | 16 ++++- src/backend/cpu/CpuConfig.cpp | 13 ++++ src/backend/cpu/CpuConfig.h | 2 + src/crypto/argon2/{Argon2.h => Hash.h} | 29 +++------ src/crypto/argon2/Impl.cpp | 62 +++++++++++++++++++ src/crypto/argon2/Impl.h | 49 +++++++++++++++ src/crypto/cn/CnHash.cpp | 10 ++-- src/crypto/cn/CryptoNight_test.h | 34 +++++++++-- 12 files changed, 258 insertions(+), 77 deletions(-) rename src/crypto/argon2/{Argon2.h => Hash.h} (68%) create mode 100644 src/crypto/argon2/Impl.cpp create mode 100644 src/crypto/argon2/Impl.h diff --git a/cmake/argon2.cmake b/cmake/argon2.cmake index 29ac9094..e82cd389 100644 --- a/cmake/argon2.cmake +++ b/cmake/argon2.cmake @@ -2,7 +2,12 @@ if (WITH_ARGON2) add_definitions(/DXMRIG_ALGO_ARGON2) list(APPEND HEADERS_CRYPTO - src/crypto/argon2/Argon2.h + src/crypto/argon2/Hash.h + src/crypto/argon2/Impl.h + ) + + list(APPEND SOURCES_CRYPTO + src/crypto/argon2/Impl.cpp ) add_subdirectory(src/3rdparty/argon2) diff --git a/src/3rdparty/argon2/CMakeLists.txt b/src/3rdparty/argon2/CMakeLists.txt index 6440a3c0..80b0056d 100644 --- a/src/3rdparty/argon2/CMakeLists.txt +++ b/src/3rdparty/argon2/CMakeLists.txt @@ -39,57 +39,54 @@ set_property(TARGET argon2 APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ARGON2_MAJOR_VERSION ) -#if (CMAKE_C_COMPILER_ID MATCHES MSVC) +if (CMAKE_C_COMPILER_ID MATCHES MSVC) -#elseif (NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8) -# function(add_feature_impl FEATURE GCC_FLAG DEF) -# add_library(argon2-${FEATURE} STATIC -# arch/x86_64/lib/argon2-${FEATURE}.c -# ) -# target_link_libraries(argon2-${FEATURE} PRIVATE argon2-internal) -# set_target_properties(argon2-${FEATURE} -# PROPERTIES POSITION_INDEPENDENT_CODE True -# ) +elseif (NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8) + function(add_feature_impl FEATURE GCC_FLAG DEF) + add_library(argon2-${FEATURE} STATIC arch/x86_64/lib/argon2-${FEATURE}.c) + target_link_libraries(argon2-${FEATURE} PRIVATE argon2-internal) + set_target_properties(argon2-${FEATURE} PROPERTIES POSITION_INDEPENDENT_CODE True) -# message("-- Detecting feature '${FEATURE}'...") -# file(READ arch/x86_64/src/test-feature-${FEATURE}.c SOURCE_CODE) + message("-- argon2: detecting feature '${FEATURE}'...") + file(READ arch/x86_64/src/test-feature-${FEATURE}.c SOURCE_CODE) -# # try without flag: -# check_c_source_compiles("${SOURCE_CODE}" FEATURE_${FEATURE}_NOFLAG) -# set(HAS_FEATURE ${FEATURE_${FEATURE}_NOFLAG}) -# if(NOT "${HAS_FEATURE}") -# # try with -m flag: -# set(CMAKE_REQUIRED_FLAGS ${GCC_FLAG}) -# check_c_source_compiles("${SOURCE_CODE}" FEATURE_${FEATURE}_FLAG) -# set(CMAKE_REQUIRED_FLAGS "") + # try without flag: + check_c_source_compiles("${SOURCE_CODE}" FEATURE_${FEATURE}_NOFLAG) + set(HAS_FEATURE ${FEATURE_${FEATURE}_NOFLAG}) + if (NOT "${HAS_FEATURE}") + # try with -m flag: + set(CMAKE_REQUIRED_FLAGS ${GCC_FLAG}) + check_c_source_compiles("${SOURCE_CODE}" FEATURE_${FEATURE}_FLAG) + set(CMAKE_REQUIRED_FLAGS "") -# set(HAS_FEATURE ${FEATURE_${FEATURE}_FLAG}) -# if(${HAS_FEATURE}) -# target_compile_options(argon2-${FEATURE} PRIVATE ${GCC_FLAG}) -# endif() -# endif() + set(HAS_FEATURE ${FEATURE_${FEATURE}_FLAG}) + if (${HAS_FEATURE}) + target_compile_options(argon2-${FEATURE} PRIVATE ${GCC_FLAG}) + endif() + endif() -# if(${HAS_FEATURE}) -# message("-- Feature '${FEATURE}' detected!") -# target_compile_definitions(argon2-${FEATURE} PRIVATE ${DEF}) -# endif() -# target_link_libraries(argon2 PUBLIC argon2-${FEATURE}) -# endfunction() + if (${HAS_FEATURE}) + message("-- argon2: feature '${FEATURE}' detected!") + target_compile_definitions(argon2-${FEATURE} PRIVATE ${DEF}) + endif() -# target_include_directories(argon2-internal INTERFACE arch/x86_64/lib) + target_link_libraries(argon2 PUBLIC argon2-${FEATURE}) + endfunction() -# add_feature_impl(sse2 -msse2 HAVE_SSE2) -# add_feature_impl(ssse3 -mssse3 HAVE_SSSE3) -# add_feature_impl(xop -mxop HAVE_XOP) -# add_feature_impl(avx2 -mavx2 HAVE_AVX2) -# add_feature_impl(avx512f -mavx512f HAVE_AVX512F) + target_include_directories(argon2-internal INTERFACE arch/x86_64/lib) -# target_sources(argon2 PRIVATE -# arch/x86_64/lib/argon2-arch.c -# arch/x86_64/lib/cpu-flags.c -# ) -#else() + add_feature_impl(sse2 -msse2 HAVE_SSE2) + add_feature_impl(ssse3 -mssse3 HAVE_SSSE3) + add_feature_impl(xop -mxop HAVE_XOP) + add_feature_impl(avx2 -mavx2 HAVE_AVX2) + add_feature_impl(avx512f -mavx512f HAVE_AVX512F) + + target_sources(argon2 PRIVATE + arch/x86_64/lib/argon2-arch.c + arch/x86_64/lib/cpu-flags.c + ) +else() target_sources(argon2 PRIVATE arch/generic/lib/argon2-arch.c ) -#endif() +endif() diff --git a/src/3rdparty/argon2/include/argon2.h b/src/3rdparty/argon2/include/argon2.h index ab4bf2f0..837e3437 100644 --- a/src/3rdparty/argon2/include/argon2.h +++ b/src/3rdparty/argon2/include/argon2.h @@ -431,6 +431,8 @@ ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, * string */ ARGON2_PUBLIC void argon2_select_impl(FILE *out, const char *prefix); +ARGON2_PUBLIC const char *argon2_get_impl_name(); +ARGON2_PUBLIC int argon2_select_impl_by_name(const char *name); /* signals support for passing preallocated memory: */ #define ARGON2_PREALLOCATED_MEMORY diff --git a/src/3rdparty/argon2/lib/impl-select.c b/src/3rdparty/argon2/lib/impl-select.c index 84c62aec..f66a04ce 100644 --- a/src/3rdparty/argon2/lib/impl-select.c +++ b/src/3rdparty/argon2/lib/impl-select.c @@ -16,7 +16,7 @@ #define BENCH_MEM_BLOCKS 512 static argon2_impl selected_argon_impl = { - "(default)", NULL, fill_segment_default + "default", NULL, fill_segment_default }; /* the benchmark routine is not thread-safe, so we can use a global var here: */ @@ -118,3 +118,29 @@ void argon2_select_impl(FILE *out, const char *prefix) } select_impl(out, prefix); } + +const char *argon2_get_impl_name() +{ + return selected_argon_impl.name; +} + + +int argon2_select_impl_by_name(const char *name) +{ + argon2_impl_list impls; + unsigned int i; + + argon2_get_impl_list(&impls); + + for (i = 0; i < impls.count; i++) { + const argon2_impl *impl = &impls.entries[i]; + + if (strcmp(impl->name, name) == 0) { + selected_argon_impl = *impl; + + return 1; + } + } + + return 0; +} diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index 77baeaf6..78cd4617 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -43,6 +43,11 @@ #include "rapidjson/document.h" +#ifdef XMRIG_ALGO_ARGON2 +# include "crypto/argon2/Impl.h" +#endif + + namespace xmrig { @@ -192,8 +197,17 @@ const xmrig::String &xmrig::CpuBackend::type() const } -void xmrig::CpuBackend::prepare(const Job &) +void xmrig::CpuBackend::prepare(const Job &nextJob) { +# ifdef XMRIG_ALGO_ARGON2 + if (nextJob.algorithm().family() == Algorithm::ARGON2 && argon2::Impl::select(d_ptr->controller->config()->cpu().argon2Impl())) { + LOG_INFO("%s use " WHITE_BOLD("argon2") " implementation " CSI "1;%dm" "%s", + tag, + argon2::Impl::name() == "default" ? 33 : 32, + argon2::Impl::name().data() + ); + } +# endif } diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 5905b7b4..87159246 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -62,6 +62,11 @@ static const char *kRx = "rx"; static const char *kRxWOW = "rx/wow"; #endif +#ifdef XMRIG_ALGO_ARGON2 +static const char *kArgon2 = "argon2"; +static const char *kArgon2Impl = "argon2-impl"; +#endif + extern template class Threads; } @@ -94,6 +99,10 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator); # endif +# ifdef XMRIG_ALGO_ARGON2 + obj.AddMember(StringRef(kArgon2Impl), m_argon2Impl.toJSON(), allocator); +# endif + m_threads.toJSON(obj, doc); return obj; @@ -132,6 +141,10 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value) m_assembly = Json::getValue(value, kAsm); # endif +# ifdef XMRIG_ALGO_ARGON2 + m_argon2Impl = Json::getString(value, kArgon2Impl); +# endif + if (!m_threads.read(value)) { generate(); } diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 5aca5188..48a3bdd4 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -55,6 +55,7 @@ public: inline bool isHugePages() const { return m_hugePages; } inline bool isShouldSave() const { return m_shouldSave; } inline const Assembly &assembly() const { return m_assembly; } + inline const String &argon2Impl() const { return m_argon2Impl; } inline const Threads &threads() const { return m_threads; } inline int priority() const { return m_priority; } @@ -70,6 +71,7 @@ private: bool m_hugePages = true; bool m_shouldSave = false; int m_priority = -1; + String m_argon2Impl; Threads m_threads; }; diff --git a/src/crypto/argon2/Argon2.h b/src/crypto/argon2/Hash.h similarity index 68% rename from src/crypto/argon2/Argon2.h rename to src/crypto/argon2/Hash.h index 709be703..743d083e 100644 --- a/src/crypto/argon2/Argon2.h +++ b/src/crypto/argon2/Hash.h @@ -22,9 +22,8 @@ * along with this program. If not, see . */ - -#ifndef XMRIG_ARGON2_H -#define XMRIG_ARGON2_H +#ifndef XMRIG_ARGON2_HASH_H +#define XMRIG_ARGON2_HASH_H #include "3rdparty/argon2.h" @@ -34,34 +33,22 @@ struct cryptonight_ctx; -namespace xmrig { +namespace xmrig { namespace argon2 { template -inline void argon2_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__, uint64_t) +inline void single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__, uint64_t) { -// static bool argon_optimization_selected = false; - -// if (!argon_optimization_selected) { -// argon2_select_impl(stdout, nullptr); - -// argon_optimization_selected = true; -// } - - uint8_t salt[16]; - - memcpy(salt, input, sizeof(salt)); - if (ALGO == Algorithm::AR2_CHUKWA) { - argon2id_hash_raw(3, 512, 1, input, size, salt, 16, output, 32); + argon2id_hash_raw(3, 512, 1, input, size, input, 16, output, 32); } else if (ALGO == Algorithm::AR2_WRKZ) { - argon2id_hash_raw(4, 256, 1, input, size, salt, 16, output, 32); + argon2id_hash_raw(4, 256, 1, input, size, input, 16, output, 32); } } -} // namespace xmrig +}} // namespace xmrig::argon2 -#endif /* XMRIG_ARGON2_H */ +#endif /* XMRIG_ARGON2_HASH_H */ diff --git a/src/crypto/argon2/Impl.cpp b/src/crypto/argon2/Impl.cpp new file mode 100644 index 00000000..0108818e --- /dev/null +++ b/src/crypto/argon2/Impl.cpp @@ -0,0 +1,62 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "3rdparty/argon2.h" +#include "base/tools/String.h" +#include "crypto/argon2/Impl.h" + + + +namespace xmrig { + + +static bool selected = false; +static String implName; + + +} // namespace xmrig + + +bool xmrig::argon2::Impl::select(const String &nameHint) +{ + if (!selected) { + if (nameHint.isEmpty() || argon2_select_impl_by_name(nameHint) == 0) { + argon2_select_impl(nullptr, nullptr); + } + + selected = true; + implName = argon2_get_impl_name(); + + return true; + } + + return false; +} + + +const xmrig::String &xmrig::argon2::Impl::name() +{ + return implName; +} diff --git a/src/crypto/argon2/Impl.h b/src/crypto/argon2/Impl.h new file mode 100644 index 00000000..006dbd35 --- /dev/null +++ b/src/crypto/argon2/Impl.h @@ -0,0 +1,49 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_ARGON2_IMPL_H +#define XMRIG_ARGON2_IMPL_H + + +namespace xmrig { + + +class String; + + +namespace argon2 { + + +class Impl +{ +public: + static bool select(const String &nameHint); + static const String &name(); +}; + + +}} // namespace xmrig::argon2 + + +#endif /* XMRIG_ARGON2_IMPL_H */ diff --git a/src/crypto/cn/CnHash.cpp b/src/crypto/cn/CnHash.cpp index dcb5a2d0..7d3ebf70 100644 --- a/src/crypto/cn/CnHash.cpp +++ b/src/crypto/cn/CnHash.cpp @@ -39,7 +39,7 @@ #ifdef XMRIG_ALGO_ARGON2 -# include "crypto/argon2/Argon2.h" +# include "crypto/argon2/Hash.h" #endif @@ -255,10 +255,10 @@ xmrig::CnHash::CnHash() # endif # ifdef XMRIG_ALGO_ARGON2 - m_map[Algorithm::AR2_CHUKWA][AV_SINGLE][Assembly::NONE] = argon2_single_hash; - m_map[Algorithm::AR2_CHUKWA][AV_SINGLE_SOFT][Assembly::NONE] = argon2_single_hash; - m_map[Algorithm::AR2_WRKZ][AV_SINGLE][Assembly::NONE] = argon2_single_hash; - m_map[Algorithm::AR2_WRKZ][AV_SINGLE_SOFT][Assembly::NONE] = argon2_single_hash; + m_map[Algorithm::AR2_CHUKWA][AV_SINGLE][Assembly::NONE] = argon2::single_hash; + m_map[Algorithm::AR2_CHUKWA][AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash; + m_map[Algorithm::AR2_WRKZ][AV_SINGLE][Assembly::NONE] = argon2::single_hash; + m_map[Algorithm::AR2_WRKZ][AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash; # endif # ifdef XMRIG_FEATURE_ASM diff --git a/src/crypto/cn/CryptoNight_test.h b/src/crypto/cn/CryptoNight_test.h index cc8130b8..4de04bb9 100644 --- a/src/crypto/cn/CryptoNight_test.h +++ b/src/crypto/cn/CryptoNight_test.h @@ -358,24 +358,48 @@ const static uint8_t test_output_pico_trtl[160] = { #ifdef XMRIG_ALGO_CN_GPU // "cn/gpu" -const static uint8_t test_output_gpu[32] = { +const static uint8_t test_output_gpu[160] = { 0xE5, 0x5C, 0xB2, 0x3E, 0x51, 0x64, 0x9A, 0x59, 0xB1, 0x27, 0xB9, 0x6B, 0x51, 0x5F, 0x2B, 0xF7, - 0xBF, 0xEA, 0x19, 0x97, 0x41, 0xA0, 0x21, 0x6C, 0xF8, 0x38, 0xDE, 0xD0, 0x6E, 0xFF, 0x82, 0xDF + 0xBF, 0xEA, 0x19, 0x97, 0x41, 0xA0, 0x21, 0x6C, 0xF8, 0x38, 0xDE, 0xD0, 0x6E, 0xFF, 0x82, 0xDF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #ifdef XMRIG_ALGO_ARGON2 // "argon2/chukwa" -const static uint8_t argon2_chukwa_test_out[32] = { +const static uint8_t argon2_chukwa_test_out[160] = { 0xC1, 0x58, 0xA1, 0x05, 0xAE, 0x75, 0xC7, 0x56, 0x1C, 0xFD, 0x02, 0x90, 0x83, 0xA4, 0x7A, 0x87, - 0x65, 0x3D, 0x51, 0xF9, 0x14, 0x12, 0x8E, 0x21, 0xC1, 0x97, 0x1D, 0x8B, 0x10, 0xC4, 0x90, 0x34 + 0x65, 0x3D, 0x51, 0xF9, 0x14, 0x12, 0x8E, 0x21, 0xC1, 0x97, 0x1D, 0x8B, 0x10, 0xC4, 0x90, 0x34, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // "argon2/wrkz" -const static uint8_t argon2_wrkz_test_out[32] = { +const static uint8_t argon2_wrkz_test_out[160] = { 0x35, 0xE0, 0x83, 0xD4, 0xB9, 0xC6, 0x4C, 0x2A, 0x68, 0x82, 0x0A, 0x43, 0x1F, 0x61, 0x31, 0x19, 0x98, 0xA8, 0xCD, 0x18, 0x64, 0xDB, 0xA4, 0x07, 0x7E, 0x25, 0xB7, 0xF1, 0x21, 0xD5, 0x4B, 0xD1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif