├── test ├── .gitignore ├── Makefile.am └── egihash_test.cpp ├── README.md ├── Makefile.am ├── data ├── .gitignore ├── ethash_eg_seed_2_hashes.dag └── headerhash_test_vectors.csv ├── autogen.sh ├── include ├── Makefile.am ├── keccak-tiny.h ├── secure_memzero.h └── egihash.h ├── .gitignore ├── libegihash ├── Makefile.am ├── keccak-tiny.c └── egihash.cpp ├── configure.ac ├── LICENSE └── m4 ├── ax_boost_system.m4 ├── ax_boost_chrono.m4 ├── ax_boost_filesystem.m4 ├── ax_boost_program_options.m4 ├── ax_boost_thread.m4 ├── ax_boost_unit_test_framework.m4 └── ax_boost_base.m4 /test/.gitignore: -------------------------------------------------------------------------------- 1 | /egihash_test 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # egihash 2 | Energi cryptocurrency hash algorithm 3 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS=libegihash include test 2 | ACLOCAL_AMFLAGS=-I m4 3 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | # Dag file used for testing 2 | 3 | /egihash.dag 4 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | autoreconf --install --force --warnings=all 5 | -------------------------------------------------------------------------------- /data/ethash_eg_seed_2_hashes.dag: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/energicryptocurrency/gen2-energihash/HEAD/data/ethash_eg_seed_2_hashes.dag -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | # These files will end up in the install include directory 2 | # For example, /usr/include 3 | include_HEADERS = egihash.h 4 | -------------------------------------------------------------------------------- /include/keccak-tiny.h: -------------------------------------------------------------------------------- 1 | #ifndef KECCAK_FIPS202_H 2 | #define KECCAK_FIPS202_H 3 | #include 4 | #include 5 | 6 | #define decshake(bits) \ 7 | int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); 8 | 9 | #define decsha3(bits) \ 10 | int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); 11 | 12 | decshake(128) 13 | decshake(256) 14 | decsha3(224) 15 | decsha3(256) 16 | decsha3(384) 17 | decsha3(512) 18 | #endif 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | /egihash 34 | 35 | # Autotools files 36 | *.deps 37 | *.m4 38 | .libs 39 | autom4te.cache 40 | compile 41 | config.guess 42 | config.log 43 | config.status 44 | config.sub 45 | configure 46 | depcomp 47 | install-sh 48 | libtool 49 | ltmain.sh 50 | Makefile 51 | Makefile.in 52 | missing 53 | -------------------------------------------------------------------------------- /libegihash/Makefile.am: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # The list of libraries we are building seperated by spaces. 3 | # The 'lib_' indicates that these build products will be installed 4 | # in the $(libdir) directory. For example /usr/lib 5 | lib_LTLIBRARIES = libegihash.la 6 | 7 | ####################################### 8 | # Build information for each library 9 | 10 | # Sources for libegihash 11 | libegihash_la_SOURCES = egihash.cpp keccak-tiny.c 12 | 13 | # Linker options libTestProgram 14 | libegihash_la_LDFLAGS = 15 | 16 | # Compiler options. Here we are adding the include directory 17 | # to be searched for headers included in the source code. 18 | libegihash_la_CPPFLAGS = -I$(top_srcdir)/include -D__STDC_WANT_LIB_EXT1__=1 -DUSE_SECURE_MEMZERO 19 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to produce a configure script. 2 | 3 | AC_PREREQ([2.69]) 4 | AC_INIT([egihash],[1.23.0]) 5 | AC_PROG_CC 6 | AC_PROG_CXX 7 | 8 | AC_CANONICAL_TARGET 9 | 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | 12 | dnl Initialize automake 13 | AM_INIT_AUTOMAKE([foreign]) 14 | 15 | dnl this allows us specify individual liking flags for each target 16 | AM_PROG_CC_C_O 17 | 18 | dnl Initialize Libtool 19 | LT_INIT 20 | 21 | 22 | #AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault]) 23 | 24 | 25 | dnl Check for boost libs 26 | AX_BOOST_BASE 27 | AX_BOOST_SYSTEM 28 | AX_BOOST_FILESYSTEM 29 | AX_BOOST_UNIT_TEST_FRAMEWORK 30 | BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB" 31 | LIBS="$BOOST_LIBS $LIBS" 32 | CPPFLAGS="$BOOST_CPPFLAGS" 33 | CXXFLAGS="$BOOST_CXXFLAGS -O3 -std=c++11 -Wall -Wextra -Werror -Wno-unused-function" 34 | CCFLAGS="$BOOST_CCFLAGS -O3 -Wall -Wextra -Werror -Wno-unused-function" 35 | 36 | 37 | AC_CONFIG_FILES(Makefile 38 | test/Makefile 39 | libegihash/Makefile 40 | include/Makefile) 41 | AC_OUTPUT 42 | 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 energicryptocurrency 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # The list of executables we are building seperated by spaces 3 | # the 'bin_' indicates that these build products will be installed 4 | # in the $(bindir) directory. For example /usr/bin 5 | #bin_PROGRAMS=egihash_test 6 | 7 | # Because a.out is only a sample program we don't want it to be installed. 8 | # The 'noinst_' prefix indicates that the following targets are not to be 9 | # installed. 10 | noinst_PROGRAMS=egihash_test 11 | 12 | ####################################### 13 | # Build information for each executable. The variable name is derived 14 | # by use the name of the executable with each non alpha-numeric character is 15 | # replaced by '_'. So a.out becomes a_out and the appropriate suffex added. 16 | # '_SOURCES' for example. 17 | 18 | ACLOCAL_AMFLAGS=-I ../m4 19 | 20 | # Sources for the a.out 21 | egihash_test_SOURCES= egihash_test.cpp 22 | 23 | # Libraries for a.out 24 | egihash_test_LDADD = $(top_srcdir)/libegihash/libegihash.la 25 | 26 | # Linker options for a.out 27 | egihash_test_LDFLAGS = -rpath `cd $(top_srcdir);pwd`/libegihash/.libs $(BOOST_UNIT_TEST_FRAMEWORK_LIB) 28 | 29 | # Compiler options for a.out 30 | egihash_test_CPPFLAGS = -I$(top_srcdir)/include -DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN 31 | -------------------------------------------------------------------------------- /m4/ax_boost_system.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_system.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_SYSTEM 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for System library from the Boost C++ libraries. The macro requires 12 | # a preceding call to AX_BOOST_BASE. Further documentation is available at 13 | # . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_SYSTEM_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_SYSTEM 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2008 Thomas Porschberg 26 | # Copyright (c) 2008 Michael Tindal 27 | # Copyright (c) 2008 Daniel Casimiro 28 | # 29 | # Copying and distribution of this file, with or without modification, are 30 | # permitted in any medium without royalty provided the copyright notice 31 | # and this notice are preserved. This file is offered as-is, without any 32 | # warranty. 33 | 34 | #serial 17 35 | 36 | AC_DEFUN([AX_BOOST_SYSTEM], 37 | [ 38 | AC_ARG_WITH([boost-system], 39 | AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@], 40 | [use the System library from boost - it is possible to specify a certain library for the linker 41 | e.g. --with-boost-system=boost_system-gcc-mt ]), 42 | [ 43 | if test "$withval" = "no"; then 44 | want_boost="no" 45 | elif test "$withval" = "yes"; then 46 | want_boost="yes" 47 | ax_boost_user_system_lib="" 48 | else 49 | want_boost="yes" 50 | ax_boost_user_system_lib="$withval" 51 | fi 52 | ], 53 | [want_boost="yes"] 54 | ) 55 | 56 | if test "x$want_boost" = "xyes"; then 57 | AC_REQUIRE([AC_PROG_CC]) 58 | AC_REQUIRE([AC_CANONICAL_BUILD]) 59 | CPPFLAGS_SAVED="$CPPFLAGS" 60 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 61 | export CPPFLAGS 62 | 63 | LDFLAGS_SAVED="$LDFLAGS" 64 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 65 | export LDFLAGS 66 | 67 | AC_CACHE_CHECK(whether the Boost::System library is available, 68 | ax_cv_boost_system, 69 | [AC_LANG_PUSH([C++]) 70 | CXXFLAGS_SAVE=$CXXFLAGS 71 | 72 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 73 | [[boost::system::system_category]])], 74 | ax_cv_boost_system=yes, ax_cv_boost_system=no) 75 | CXXFLAGS=$CXXFLAGS_SAVE 76 | AC_LANG_POP([C++]) 77 | ]) 78 | if test "x$ax_cv_boost_system" = "xyes"; then 79 | AC_SUBST(BOOST_CPPFLAGS) 80 | 81 | AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available]) 82 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 83 | 84 | LDFLAGS_SAVE=$LDFLAGS 85 | if test "x$ax_boost_user_system_lib" = "x"; then 86 | ax_lib= 87 | for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do 88 | ax_lib=${libextension} 89 | AC_CHECK_LIB($ax_lib, exit, 90 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 91 | [link_system="no"]) 92 | done 93 | if test "x$link_system" != "xyes"; then 94 | for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do 95 | ax_lib=${libextension} 96 | AC_CHECK_LIB($ax_lib, exit, 97 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 98 | [link_system="no"]) 99 | done 100 | fi 101 | 102 | else 103 | for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do 104 | AC_CHECK_LIB($ax_lib, exit, 105 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 106 | [link_system="no"]) 107 | done 108 | 109 | fi 110 | if test "x$ax_lib" = "x"; then 111 | AC_MSG_ERROR(Could not find a version of the boost_system library!) 112 | fi 113 | if test "x$link_system" = "xno"; then 114 | AC_MSG_ERROR(Could not link against $ax_lib !) 115 | fi 116 | fi 117 | 118 | CPPFLAGS="$CPPFLAGS_SAVED" 119 | LDFLAGS="$LDFLAGS_SAVED" 120 | fi 121 | ]) 122 | -------------------------------------------------------------------------------- /m4/ax_boost_chrono.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_CHRONO 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for System library from the Boost C++ libraries. The macro requires 12 | # a preceding call to AX_BOOST_BASE. Further documentation is available at 13 | # . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_CHRONO_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_CHRONO 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2012 Xiyue Deng 26 | # 27 | # Copying and distribution of this file, with or without modification, are 28 | # permitted in any medium without royalty provided the copyright notice 29 | # and this notice are preserved. This file is offered as-is, without any 30 | # warranty. 31 | 32 | #serial 1 33 | 34 | AC_DEFUN([AX_BOOST_CHRONO], 35 | [ 36 | AC_ARG_WITH([boost-chrono], 37 | AS_HELP_STRING([--with-boost-chrono@<:@=special-lib@:>@], 38 | [use the Chrono library from boost - it is possible to specify a certain library for the linker 39 | e.g. --with-boost-chrono=boost_chrono-gcc-mt ]), 40 | [ 41 | if test "$withval" = "no"; then 42 | want_boost="no" 43 | elif test "$withval" = "yes"; then 44 | want_boost="yes" 45 | ax_boost_user_chrono_lib="" 46 | else 47 | want_boost="yes" 48 | ax_boost_user_chrono_lib="$withval" 49 | fi 50 | ], 51 | [want_boost="yes"] 52 | ) 53 | 54 | if test "x$want_boost" = "xyes"; then 55 | AC_REQUIRE([AC_PROG_CC]) 56 | AC_REQUIRE([AC_CANONICAL_BUILD]) 57 | CPPFLAGS_SAVED="$CPPFLAGS" 58 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 59 | export CPPFLAGS 60 | 61 | LDFLAGS_SAVED="$LDFLAGS" 62 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 63 | export LDFLAGS 64 | 65 | AC_CACHE_CHECK(whether the Boost::Chrono library is available, 66 | ax_cv_boost_chrono, 67 | [AC_LANG_PUSH([C++]) 68 | CXXFLAGS_SAVE=$CXXFLAGS 69 | 70 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 71 | [[boost::chrono::system_clock::time_point time;]])], 72 | ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no) 73 | CXXFLAGS=$CXXFLAGS_SAVE 74 | AC_LANG_POP([C++]) 75 | ]) 76 | if test "x$ax_cv_boost_chrono" = "xyes"; then 77 | AC_SUBST(BOOST_CPPFLAGS) 78 | 79 | AC_DEFINE(HAVE_BOOST_CHRONO,,[define if the Boost::Chrono library is available]) 80 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 81 | 82 | LDFLAGS_SAVE=$LDFLAGS 83 | if test "x$ax_boost_user_chrono_lib" = "x"; then 84 | ax_lib= 85 | for libextension in `ls $BOOSTLIBDIR/libboost_chrono*.so* $BOOSTLIBDIR/libboost_chrono*.dylib* $BOOSTLIBDIR/libboost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_chrono.*\)\.so.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.a.*$;\1;'` ; do 86 | ax_lib=${libextension} 87 | AC_CHECK_LIB($ax_lib, exit, 88 | [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break], 89 | [link_chrono="no"]) 90 | done 91 | if test "x$link_chrono" != "xyes"; then 92 | for libextension in `ls $BOOSTLIBDIR/boost_chrono*.dll* $BOOSTLIBDIR/boost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_chrono.*\)\.dll.*$;\1;' -e 's;^\(boost_chrono.*\)\.a.*$;\1;'` ; do 93 | ax_lib=${libextension} 94 | AC_CHECK_LIB($ax_lib, exit, 95 | [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break], 96 | [link_chrono="no"]) 97 | done 98 | fi 99 | 100 | else 101 | for ax_lib in $ax_boost_user_chrono_lib boost_chrono-$ax_boost_user_chrono_lib; do 102 | AC_CHECK_LIB($ax_lib, exit, 103 | [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break], 104 | [link_chrono="no"]) 105 | done 106 | 107 | fi 108 | if test "x$ax_lib" = "x"; then 109 | AC_MSG_ERROR(Could not find a version of the boost_chrono library!) 110 | fi 111 | if test "x$link_chrono" = "xno"; then 112 | AC_MSG_ERROR(Could not link against $ax_lib !) 113 | fi 114 | fi 115 | 116 | CPPFLAGS="$CPPFLAGS_SAVED" 117 | LDFLAGS="$LDFLAGS_SAVED" 118 | fi 119 | ]) 120 | -------------------------------------------------------------------------------- /m4/ax_boost_filesystem.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_FILESYSTEM 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Filesystem library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_FILESYSTEM_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_FILESYSTEM 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2009 Thomas Porschberg 26 | # Copyright (c) 2009 Michael Tindal 27 | # Copyright (c) 2009 Roman Rybalko 28 | # 29 | # Copying and distribution of this file, with or without modification, are 30 | # permitted in any medium without royalty provided the copyright notice 31 | # and this notice are preserved. This file is offered as-is, without any 32 | # warranty. 33 | 34 | #serial 26 35 | 36 | AC_DEFUN([AX_BOOST_FILESYSTEM], 37 | [ 38 | AC_ARG_WITH([boost-filesystem], 39 | AS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@], 40 | [use the Filesystem library from boost - it is possible to specify a certain library for the linker 41 | e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]), 42 | [ 43 | if test "$withval" = "no"; then 44 | want_boost="no" 45 | elif test "$withval" = "yes"; then 46 | want_boost="yes" 47 | ax_boost_user_filesystem_lib="" 48 | else 49 | want_boost="yes" 50 | ax_boost_user_filesystem_lib="$withval" 51 | fi 52 | ], 53 | [want_boost="yes"] 54 | ) 55 | 56 | if test "x$want_boost" = "xyes"; then 57 | AC_REQUIRE([AC_PROG_CC]) 58 | CPPFLAGS_SAVED="$CPPFLAGS" 59 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 60 | export CPPFLAGS 61 | 62 | LDFLAGS_SAVED="$LDFLAGS" 63 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 64 | export LDFLAGS 65 | 66 | LIBS_SAVED=$LIBS 67 | LIBS="$LIBS $BOOST_SYSTEM_LIB" 68 | export LIBS 69 | 70 | AC_CACHE_CHECK(whether the Boost::Filesystem library is available, 71 | ax_cv_boost_filesystem, 72 | [AC_LANG_PUSH([C++]) 73 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 74 | [[using namespace boost::filesystem; 75 | path my_path( "foo/bar/data.txt" ); 76 | return 0;]])], 77 | ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no) 78 | AC_LANG_POP([C++]) 79 | ]) 80 | if test "x$ax_cv_boost_filesystem" = "xyes"; then 81 | AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available]) 82 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 83 | ax_lib= 84 | if test "x$ax_boost_user_filesystem_lib" = "x"; then 85 | for libextension in `ls -r $BOOSTLIBDIR/libboost_filesystem* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do 86 | ax_lib=${libextension} 87 | AC_CHECK_LIB($ax_lib, exit, 88 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 89 | [link_filesystem="no"]) 90 | done 91 | if test "x$link_filesystem" != "xyes"; then 92 | for libextension in `ls -r $BOOSTLIBDIR/boost_filesystem* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do 93 | ax_lib=${libextension} 94 | AC_CHECK_LIB($ax_lib, exit, 95 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 96 | [link_filesystem="no"]) 97 | done 98 | fi 99 | else 100 | for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do 101 | AC_CHECK_LIB($ax_lib, exit, 102 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 103 | [link_filesystem="no"]) 104 | done 105 | 106 | fi 107 | if test "x$ax_lib" = "x"; then 108 | AC_MSG_ERROR(Could not find a version of the boost_filesystem library!) 109 | fi 110 | if test "x$link_filesystem" != "xyes"; then 111 | AC_MSG_ERROR(Could not link against $ax_lib !) 112 | fi 113 | fi 114 | 115 | CPPFLAGS="$CPPFLAGS_SAVED" 116 | LDFLAGS="$LDFLAGS_SAVED" 117 | LIBS="$LIBS_SAVED" 118 | fi 119 | ]) 120 | -------------------------------------------------------------------------------- /m4/ax_boost_program_options.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_program_options.html 3 | # ============================================================================ 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_PROGRAM_OPTIONS 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for program options library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_PROGRAM_OPTIONS 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2009 Thomas Porschberg 26 | # 27 | # Copying and distribution of this file, with or without modification, are 28 | # permitted in any medium without royalty provided the copyright notice 29 | # and this notice are preserved. This file is offered as-is, without any 30 | # warranty. 31 | 32 | #serial 22 33 | 34 | AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], 35 | [ 36 | AC_ARG_WITH([boost-program-options], 37 | AS_HELP_STRING([--with-boost-program-options@<:@=special-lib@:>@], 38 | [use the program options library from boost - it is possible to specify a certain library for the linker 39 | e.g. --with-boost-program-options=boost_program_options-gcc-mt-1_33_1 ]), 40 | [ 41 | if test "$withval" = "no"; then 42 | want_boost="no" 43 | elif test "$withval" = "yes"; then 44 | want_boost="yes" 45 | ax_boost_user_program_options_lib="" 46 | else 47 | want_boost="yes" 48 | ax_boost_user_program_options_lib="$withval" 49 | fi 50 | ], 51 | [want_boost="yes"] 52 | ) 53 | 54 | if test "x$want_boost" = "xyes"; then 55 | AC_REQUIRE([AC_PROG_CC]) 56 | export want_boost 57 | CPPFLAGS_SAVED="$CPPFLAGS" 58 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 59 | export CPPFLAGS 60 | LDFLAGS_SAVED="$LDFLAGS" 61 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 62 | export LDFLAGS 63 | AC_CACHE_CHECK([whether the Boost::Program_Options library is available], 64 | ax_cv_boost_program_options, 65 | [AC_LANG_PUSH(C++) 66 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include 67 | ]], 68 | [[boost::program_options::options_description generic("Generic options"); 69 | return 0;]])], 70 | ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no) 71 | AC_LANG_POP([C++]) 72 | ]) 73 | if test "$ax_cv_boost_program_options" = yes; then 74 | AC_DEFINE(HAVE_BOOST_PROGRAM_OPTIONS,,[define if the Boost::PROGRAM_OPTIONS library is available]) 75 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 76 | if test "x$ax_boost_user_program_options_lib" = "x"; then 77 | ax_lib= 78 | for libextension in `ls $BOOSTLIBDIR/libboost_program_options*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.dylib* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.dylib.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.a.*$;\1;'` ; do 79 | ax_lib=${libextension} 80 | AC_CHECK_LIB($ax_lib, exit, 81 | [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break], 82 | [link_program_options="no"]) 83 | done 84 | if test "x$link_program_options" != "xyes"; then 85 | for libextension in `ls $BOOSTLIBDIR/boost_program_options*.dll* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.dll.*$;\1;'` `ls $BOOSTLIBDIR/boost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.a.*$;\1;'` ; do 86 | ax_lib=${libextension} 87 | AC_CHECK_LIB($ax_lib, exit, 88 | [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break], 89 | [link_program_options="no"]) 90 | done 91 | fi 92 | else 93 | for ax_lib in $ax_boost_user_program_options_lib boost_program_options-$ax_boost_user_program_options_lib; do 94 | AC_CHECK_LIB($ax_lib, main, 95 | [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break], 96 | [link_program_options="no"]) 97 | done 98 | fi 99 | if test "x$ax_lib" = "x"; then 100 | AC_MSG_ERROR(Could not find a version of the boost_program_options library!) 101 | fi 102 | if test "x$link_program_options" != "xyes"; then 103 | AC_MSG_ERROR([Could not link against [$ax_lib] !]) 104 | fi 105 | fi 106 | CPPFLAGS="$CPPFLAGS_SAVED" 107 | LDFLAGS="$LDFLAGS_SAVED" 108 | fi 109 | ]) 110 | -------------------------------------------------------------------------------- /m4/ax_boost_thread.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_THREAD 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Thread library from the Boost C++ libraries. The macro requires 12 | # a preceding call to AX_BOOST_BASE. Further documentation is available at 13 | # . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_THREAD_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_THREAD 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2009 Thomas Porschberg 26 | # Copyright (c) 2009 Michael Tindal 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 27 34 | 35 | AC_DEFUN([AX_BOOST_THREAD], 36 | [ 37 | AC_ARG_WITH([boost-thread], 38 | AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@], 39 | [use the Thread library from boost - it is possible to specify a certain library for the linker 40 | e.g. --with-boost-thread=boost_thread-gcc-mt ]), 41 | [ 42 | if test "$withval" = "no"; then 43 | want_boost="no" 44 | elif test "$withval" = "yes"; then 45 | want_boost="yes" 46 | ax_boost_user_thread_lib="" 47 | else 48 | want_boost="yes" 49 | ax_boost_user_thread_lib="$withval" 50 | fi 51 | ], 52 | [want_boost="yes"] 53 | ) 54 | 55 | if test "x$want_boost" = "xyes"; then 56 | AC_REQUIRE([AC_PROG_CC]) 57 | AC_REQUIRE([AC_CANONICAL_BUILD]) 58 | CPPFLAGS_SAVED="$CPPFLAGS" 59 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 60 | export CPPFLAGS 61 | 62 | LDFLAGS_SAVED="$LDFLAGS" 63 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 64 | export LDFLAGS 65 | 66 | AC_CACHE_CHECK(whether the Boost::Thread library is available, 67 | ax_cv_boost_thread, 68 | [AC_LANG_PUSH([C++]) 69 | CXXFLAGS_SAVE=$CXXFLAGS 70 | 71 | if test "x$host_os" = "xsolaris" ; then 72 | CXXFLAGS="-pthreads $CXXFLAGS" 73 | elif test "x$host_os" = "xmingw32" ; then 74 | CXXFLAGS="-mthreads $CXXFLAGS" 75 | else 76 | CXXFLAGS="-pthread $CXXFLAGS" 77 | fi 78 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 79 | [[boost::thread_group thrds; 80 | return 0;]])], 81 | ax_cv_boost_thread=yes, ax_cv_boost_thread=no) 82 | CXXFLAGS=$CXXFLAGS_SAVE 83 | AC_LANG_POP([C++]) 84 | ]) 85 | if test "x$ax_cv_boost_thread" = "xyes"; then 86 | if test "x$host_os" = "xsolaris" ; then 87 | BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" 88 | elif test "x$host_os" = "xmingw32" ; then 89 | BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" 90 | else 91 | BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" 92 | fi 93 | 94 | AC_SUBST(BOOST_CPPFLAGS) 95 | 96 | AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available]) 97 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 98 | 99 | LDFLAGS_SAVE=$LDFLAGS 100 | case "x$host_os" in 101 | *bsd* ) 102 | LDFLAGS="-pthread $LDFLAGS" 103 | break; 104 | ;; 105 | esac 106 | if test "x$ax_boost_user_thread_lib" = "x"; then 107 | ax_lib= 108 | for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do 109 | ax_lib=${libextension} 110 | AC_CHECK_LIB($ax_lib, exit, 111 | [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], 112 | [link_thread="no"]) 113 | done 114 | if test "x$link_thread" != "xyes"; then 115 | for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do 116 | ax_lib=${libextension} 117 | AC_CHECK_LIB($ax_lib, exit, 118 | [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], 119 | [link_thread="no"]) 120 | done 121 | fi 122 | 123 | else 124 | for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do 125 | AC_CHECK_LIB($ax_lib, exit, 126 | [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], 127 | [link_thread="no"]) 128 | done 129 | 130 | fi 131 | if test "x$ax_lib" = "x"; then 132 | AC_MSG_ERROR(Could not find a version of the boost_thread library!) 133 | fi 134 | if test "x$link_thread" = "xno"; then 135 | AC_MSG_ERROR(Could not link against $ax_lib !) 136 | else 137 | case "x$host_os" in 138 | *bsd* ) 139 | BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" 140 | break; 141 | ;; 142 | esac 143 | 144 | fi 145 | fi 146 | 147 | CPPFLAGS="$CPPFLAGS_SAVED" 148 | LDFLAGS="$LDFLAGS_SAVED" 149 | fi 150 | ]) 151 | -------------------------------------------------------------------------------- /libegihash/keccak-tiny.c: -------------------------------------------------------------------------------- 1 | /** libkeccak-tiny 2 | * 3 | * A single-file implementation of SHA-3 and SHAKE. 4 | * 5 | * Implementor: David Leon Gil 6 | * License: CC0, attribution kindly requested. Blame taken too, 7 | * but not liability. 8 | */ 9 | #include "keccak-tiny.h" 10 | 11 | #ifdef USE_SECURE_MEMZERO 12 | #include "secure_memzero.h" 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /******** The Keccak-f[1600] permutation ********/ 21 | 22 | /*** Constants. ***/ 23 | static const uint8_t rho[24] = \ 24 | { 1, 3, 6, 10, 15, 21, 25 | 28, 36, 45, 55, 2, 14, 26 | 27, 41, 56, 8, 25, 43, 27 | 62, 18, 39, 61, 20, 44}; 28 | static const uint8_t pi[24] = \ 29 | {10, 7, 11, 17, 18, 3, 30 | 5, 16, 8, 21, 24, 4, 31 | 15, 23, 19, 13, 12, 2, 32 | 20, 14, 22, 9, 6, 1}; 33 | static const uint64_t RC[24] = \ 34 | {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, 35 | 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, 36 | 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, 37 | 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, 38 | 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, 39 | 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; 40 | 41 | /*** Helper macros to unroll the permutation. ***/ 42 | #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) 43 | #define REPEAT6(e) e e e e e e 44 | #define REPEAT24(e) REPEAT6(e e e e) 45 | #define REPEAT5(e) e e e e e 46 | #define FOR5(v, s, e) \ 47 | v = 0; \ 48 | REPEAT5(e; v += s;) 49 | 50 | /*** Keccak-f[1600] ***/ 51 | static inline void keccakf(void* state) { 52 | uint64_t* a = (uint64_t*)state; 53 | uint64_t b[5] = {0}; 54 | uint64_t t = 0; 55 | uint8_t x, y; 56 | 57 | for (int i = 0; i < 24; i++) { 58 | // Theta 59 | FOR5(x, 1, 60 | b[x] = 0; 61 | FOR5(y, 5, 62 | b[x] ^= a[x + y]; )) 63 | FOR5(x, 1, 64 | FOR5(y, 5, 65 | a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) 66 | // Rho and pi 67 | t = a[1]; 68 | x = 0; 69 | REPEAT24(b[0] = a[pi[x]]; 70 | a[pi[x]] = rol(t, rho[x]); 71 | t = b[0]; 72 | x++; ) 73 | // Chi 74 | FOR5(y, 75 | 5, 76 | FOR5(x, 1, 77 | b[x] = a[y + x];) 78 | FOR5(x, 1, 79 | a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) 80 | // Iota 81 | a[0] ^= RC[i]; 82 | } 83 | } 84 | 85 | /******** The FIPS202-defined functions. ********/ 86 | 87 | /*** Some helper macros. ***/ 88 | 89 | #define _(S) do { S } while (0) 90 | #define FOR(i, ST, L, S) \ 91 | _(for (size_t i = 0; i < L; i += ST) { S; }) 92 | #define mkapply_ds(NAME, S) \ 93 | static inline void NAME(uint8_t* dst, \ 94 | const uint8_t* src, \ 95 | size_t len) { \ 96 | FOR(i, 1, len, S); \ 97 | } 98 | #define mkapply_sd(NAME, S) \ 99 | static inline void NAME(const uint8_t* src, \ 100 | uint8_t* dst, \ 101 | size_t len) { \ 102 | FOR(i, 1, len, S); \ 103 | } 104 | 105 | mkapply_ds(xorin, dst[i] ^= src[i]) // xorin 106 | mkapply_sd(setout, dst[i] = src[i]) // setout 107 | 108 | #define P keccakf 109 | #define Plen 200 110 | 111 | // Fold P*F over the full blocks of an input. 112 | #define foldP(I, L, F) \ 113 | while (L >= rate) { \ 114 | F(a, I, rate); \ 115 | P(a); \ 116 | I += rate; \ 117 | L -= rate; \ 118 | } 119 | 120 | /** The sponge-based hash construction. **/ 121 | static inline int hash(uint8_t* out, size_t outlen, 122 | const uint8_t* in, size_t inlen, 123 | size_t rate, uint8_t delim) { 124 | if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { 125 | return -1; 126 | } 127 | uint8_t a[Plen] = {0}; 128 | // Absorb input. 129 | foldP(in, inlen, xorin); 130 | // Xor in the DS and pad frame. 131 | a[inlen] ^= delim; 132 | a[rate - 1] ^= 0x80; 133 | // Xor in the last block. 134 | xorin(a, in, inlen); 135 | // Apply P 136 | P(a); 137 | // Squeeze output. 138 | foldP(out, outlen, setout); 139 | setout(a, out, outlen); 140 | #ifdef USE_SECURE_MEMZERO 141 | secure_memzero(a, 200); 142 | #else 143 | memset_s(a, 200, 0, 200); 144 | #endif 145 | return 0; 146 | } 147 | 148 | /*** Helper macros to define SHA3 and SHAKE instances. ***/ 149 | #define defshake(bits) \ 150 | int shake##bits(uint8_t* out, size_t outlen, \ 151 | const uint8_t* in, size_t inlen) { \ 152 | return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ 153 | } 154 | #define defsha3(bits) \ 155 | int sha3_##bits(uint8_t* out, size_t outlen, \ 156 | const uint8_t* in, size_t inlen) { \ 157 | if (outlen > (bits/8)) { \ 158 | return -1; \ 159 | } \ 160 | return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ 161 | } 162 | 163 | /*** FIPS202 SHAKE VOFs ***/ 164 | defshake(128) 165 | defshake(256) 166 | 167 | /*** FIPS202 SHA3 FOFs ***/ 168 | defsha3(224) 169 | defsha3(256) 170 | defsha3(384) 171 | defsha3(512) 172 | -------------------------------------------------------------------------------- /m4/ax_boost_unit_test_framework.m4: -------------------------------------------------------------------------------- 1 | # ================================================================================ 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html 3 | # ================================================================================ 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_UNIT_TEST_FRAMEWORK 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Unit_Test_Framework library from the Boost C++ libraries. The 12 | # macro requires a preceding call to AX_BOOST_BASE. Further documentation 13 | # is available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_UNIT_TEST_FRAMEWORK 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2008 Thomas Porschberg 26 | # 27 | # Copying and distribution of this file, with or without modification, are 28 | # permitted in any medium without royalty provided the copyright notice 29 | # and this notice are preserved. This file is offered as-is, without any 30 | # warranty. 31 | 32 | #serial 19 33 | 34 | AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], 35 | [ 36 | AC_ARG_WITH([boost-unit-test-framework], 37 | AS_HELP_STRING([--with-boost-unit-test-framework@<:@=special-lib@:>@], 38 | [use the Unit_Test_Framework library from boost - it is possible to specify a certain library for the linker 39 | e.g. --with-boost-unit-test-framework=boost_unit_test_framework-gcc ]), 40 | [ 41 | if test "$withval" = "no"; then 42 | want_boost="no" 43 | elif test "$withval" = "yes"; then 44 | want_boost="yes" 45 | ax_boost_user_unit_test_framework_lib="" 46 | else 47 | want_boost="yes" 48 | ax_boost_user_unit_test_framework_lib="$withval" 49 | fi 50 | ], 51 | [want_boost="yes"] 52 | ) 53 | 54 | if test "x$want_boost" = "xyes"; then 55 | AC_REQUIRE([AC_PROG_CC]) 56 | CPPFLAGS_SAVED="$CPPFLAGS" 57 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 58 | export CPPFLAGS 59 | 60 | LDFLAGS_SAVED="$LDFLAGS" 61 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 62 | export LDFLAGS 63 | 64 | AC_CACHE_CHECK(whether the Boost::Unit_Test_Framework library is available, 65 | ax_cv_boost_unit_test_framework, 66 | [AC_LANG_PUSH([C++]) 67 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 68 | [[using boost::unit_test::test_suite; 69 | test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); return 0;]])], 70 | ax_cv_boost_unit_test_framework=yes, ax_cv_boost_unit_test_framework=no) 71 | AC_LANG_POP([C++]) 72 | ]) 73 | if test "x$ax_cv_boost_unit_test_framework" = "xyes"; then 74 | AC_DEFINE(HAVE_BOOST_UNIT_TEST_FRAMEWORK,,[define if the Boost::Unit_Test_Framework library is available]) 75 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 76 | 77 | if test "x$ax_boost_user_unit_test_framework_lib" = "x"; then 78 | saved_ldflags="${LDFLAGS}" 79 | ax_lib= 80 | for monitor_library in `ls $BOOSTLIBDIR/libboost_unit_test_framework*.so* $BOOSTLIBDIR/libboost_unit_test_framework*.dylib* $BOOSTLIBDIR/libboost_unit_test_framework*.a* 2>/dev/null` ; do 81 | if test -r $monitor_library ; then 82 | libextension=`echo $monitor_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a.*$;\1;'` 83 | ax_lib=${libextension} 84 | link_unit_test_framework="yes" 85 | else 86 | link_unit_test_framework="no" 87 | fi 88 | 89 | if test "x$link_unit_test_framework" = "xyes"; then 90 | BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib" 91 | AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) 92 | break 93 | fi 94 | done 95 | if test "x$link_unit_test_framework" != "xyes"; then 96 | for libextension in `ls $BOOSTLIBDIR/boost_unit_test_framework*.dll* $BOOSTLIBDIR/boost_unit_test_framework*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_unit_test_framework.*\)\.dll.*$;\1;' -e 's;^\(boost_unit_test_framework.*\)\.a.*$;\1;'` ; do 97 | ax_lib=${libextension} 98 | AC_CHECK_LIB($ax_lib, exit, 99 | [BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib"; AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) link_unit_test_framework="yes"; break], 100 | [link_unit_test_framework="no"]) 101 | done 102 | fi 103 | else 104 | link_unit_test_framework="no" 105 | saved_ldflags="${LDFLAGS}" 106 | for ax_lib in boost_unit_test_framework-$ax_boost_user_unit_test_framework_lib $ax_boost_user_unit_test_framework_lib ; do 107 | if test "x$link_unit_test_framework" = "xyes"; then 108 | break; 109 | fi 110 | for unittest_library in `ls $BOOSTLIBDIR/lib${ax_lib}.so* $BOOSTLIBDIR/lib${ax_lib}.a* 2>/dev/null` ; do 111 | if test -r $unittest_library ; then 112 | libextension=`echo $unittest_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a*$;\1;'` 113 | ax_lib=${libextension} 114 | link_unit_test_framework="yes" 115 | else 116 | link_unit_test_framework="no" 117 | fi 118 | 119 | if test "x$link_unit_test_framework" = "xyes"; then 120 | BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib" 121 | AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) 122 | break 123 | fi 124 | done 125 | done 126 | fi 127 | if test "x$ax_lib" = "x"; then 128 | AC_MSG_ERROR(Could not find a version of the boost_unit_test_framework library!) 129 | fi 130 | if test "x$link_unit_test_framework" != "xyes"; then 131 | AC_MSG_ERROR(Could not link against $ax_lib !) 132 | fi 133 | fi 134 | 135 | CPPFLAGS="$CPPFLAGS_SAVED" 136 | LDFLAGS="$LDFLAGS_SAVED" 137 | fi 138 | ]) 139 | -------------------------------------------------------------------------------- /include/secure_memzero.h: -------------------------------------------------------------------------------- 1 | // secure_memzero.h version 1 (October 29, 2016) 2 | // 3 | // This code is released into the public domain. 4 | // 5 | // THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 6 | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 7 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 8 | // AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 9 | // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 11 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 12 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 13 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 14 | // POSSIBILITY OF SUCH DAMAGE. 15 | 16 | // The secure_memzero macro/function attempts to ensure that an optimizing 17 | // compiler does not remove the intended operation if cleared memory is not 18 | // accessed again by the program. There are several known ways of doing this, 19 | // however no single one is both universally available and absolutely guranteed 20 | // by the standard. The following code defines secure_memzero as a macro or 21 | // function using one of the known alternatives. The choice of implementation 22 | // can be controlled by defining a preprocessor macro of the form SMZ_impl, 23 | // where is one of the defined implementation names. SMZ_impl should 24 | // expand to an integer indicating the dgeree of preference for the 25 | // implementation, where numerically higher values indicate greater preference. 26 | // Defining SMZ_impl to be 0 disables the implementation even if it is 27 | // available. Not defining any SMZ_impl will result in default (safe) behavior. 28 | // 29 | // The following implementations may be used. 30 | // 31 | // SMZ_SECUREZEROMEMORY 32 | // Uses the SecureZeroMemory macro/function on Windows. Requires a Windows 33 | // environment (_WIN32 must be defined). 34 | // 35 | // SMZ_ASM_BARRIER 36 | // Uses a compiler memory barrier to force the results of a memset to be 37 | // committed to memory. Has been tested to work on: 38 | // - Clang 3.9.0 at all optimization levels. 39 | // - GCC 6.2 at all optimization levels. 40 | // 41 | // SMZ_MEMSET_S 42 | // Uses the C11 function memset_s. Currently not available on many platforms. 43 | // Note that if you want this option, you have to set __STDC_WANT_LIB_EXT1__ 44 | // to 1 before including string.h or any file that includes string.h in a 45 | // compilation unit that includes this header. 46 | // 47 | // SMZ_VDATAPTR 48 | // Uses the volatile data pointer technique to zero one byte at a time. This is 49 | // not guaranteed to work by the C standard, which does not require access to 50 | // non-volatile objects via a pointer-to-volatile to be treated as a volatile 51 | // access. However, it is known to work on the following compilers: 52 | // - Clang 3.9.0 at all optimization levels. 53 | // - GCC 6.2 at all optimization levels. 54 | // 55 | // SMZ_VFUNCPTR 56 | // Uses the volatile function pointer technique to call memset. This is not 57 | // guaranteed to work by the C standard, which does not require the pointed-to 58 | // function to be called. However, it is known to work on the following 59 | // compilers: 60 | // - Clang 3.9.0 at all optimization levels. 61 | // - GCC 6.2 at all optimization levels. 62 | 63 | // The remainder of this file implements the selection logic using the 64 | // specified compile-time preferences. 65 | 66 | #ifndef _SECURE_MEMZERO_H_ 67 | #define _SECURE_MEMZERO_H_ 68 | 69 | // STEP 1. Set default preference for all implementations to 1. 70 | 71 | #ifndef SMZ_SECUREZEROMEMORY 72 | #define SMZ_SECUREZEROMEMORY 1 73 | #endif 74 | 75 | #ifndef SMZ_MEMSET_S 76 | #define SMZ_MEMSET_S 1 77 | #endif 78 | 79 | #ifndef SMZ_ASM_BARRIER 80 | #define SMZ_ASM_BARRIER 1 81 | #endif 82 | 83 | #ifndef SMZ_VDATAPTR 84 | #define SMZ_VDATAPTR 1 85 | #endif 86 | 87 | #ifndef SMZ_VFUNCPTR 88 | #define SMZ_VFUNCPTR 1 89 | #endif 90 | 91 | // STEP 2. Check which implementations are available and include any necessary 92 | // header files. 93 | 94 | #if SMZ_SECUREZEROMEMORY > 0 95 | #ifdef _WIN32 96 | #include 97 | #else 98 | #undef SMZ_SECUREZEROMEMORY 99 | #define SMZ_SECUREZEROMEMORY 0 100 | #endif 101 | #endif 102 | 103 | #if SMZ_MEMSET_S > 0 104 | #if defined(__STDC_WANT_LIB_EXT1__) && (__STDC_WANT_LIB_EXT1__ != 1) 105 | #undef SMZ_MEMSET_S 106 | #define SMZ_MEMSET_S 0 107 | #endif 108 | #if SMZ_MEMSET_S > 0 109 | #ifndef __STDC_WANT_LIB_EXT1__ 110 | // Must come before first include of string.h 111 | #define __STDC_WANT_LIB_EXT1__ 1 112 | #endif 113 | #include 114 | #ifndef __STDC_LIB_EXT1__ 115 | #undef SMZ_MEMSET_S 116 | #define SMZ_MEMSET_S 0 117 | #endif 118 | #endif 119 | #endif 120 | 121 | #if !defined(__GNUC__) && !defined(__clang__) 122 | #undef SMZ_ASM_BARRIER 123 | #define SMZ_ASM_BARRIER 0 124 | #endif 125 | 126 | #if SMZ_VFUNCPTR > 0 127 | #include 128 | #endif 129 | 130 | // STEP 3. Calculate highest preference. 131 | 132 | #define SMZ_PREFERENCE 0 133 | 134 | #if SMZ_PREFERENCE < SMZ_SECUREZEROMEMORY 135 | #undef SMZ_PREFERENCE 136 | #define SMZ_PREFERENCE SMZ_SECUREZEROMEMORY 137 | #endif 138 | 139 | #if SMZ_PREFERENCE < SMZ_MEMSET_S 140 | #undef SMZ_PREFERENCE 141 | #define SMZ_PREFERENCE SMZ_MEMSET_S 142 | #endif 143 | 144 | #if SMZ_PREFERENCE < SMZ_ASM_BARRIER 145 | #undef SMZ_PREFERENCE 146 | #define SMZ_PREFERENCE SMZ_ASM_BARRIER 147 | #endif 148 | 149 | #if SMZ_PREFERENCE < SMZ_VDATAPTR 150 | #undef SMZ_PREFERENCE 151 | #define SMZ_PREFERENCE SMZ_VDATAPTR 152 | #endif 153 | 154 | #if SMZ_PREFERENCE < SMZ_VFUNCPTR 155 | #undef SMZ_PREFERENCE 156 | #define SMZ_PREFERENCE SMZ_VFUNCPTR 157 | #endif 158 | 159 | // STEP 4. Make sure we have something chosen. 160 | 161 | #if SMZ_PREFERENCE <= 0 162 | #error No secure_memzero implementation available 163 | #endif 164 | 165 | // STEP 5. Use implementation with highest preference. Ties are broken in 166 | // favor of implementations appearing first, below. 167 | 168 | #if SMZ_PREFERENCE == SMZ_SECUREZEROMEMORY 169 | #define secure_memzero(ptr,len) SecureZeroMemory((ptr),(len)) 170 | 171 | #elif SMZ_PREFERENCE == SMZ_MEMSET_S 172 | #define secure_memzero(ptr,len) memset_s((ptr),(len),0,(len)) 173 | 174 | #elif SMZ_PREFERENCE == SMZ_ASM_BARRIER 175 | #define secure_memzero(ptr,len) do { \ 176 | memset((ptr),0,(len)); \ 177 | __asm__ __volatile__("" ::"r"(ptr): "memory"); \ 178 | } while (0) 179 | 180 | #elif SMZ_PREFERENCE == SMZ_VDATAPTR 181 | static void secure_memzero(void * ptr, size_t len) { 182 | volatile char * p = ptr; 183 | while (len--) *p++ = 0; 184 | } 185 | 186 | #elif SMZ_PREFERENCE == SMZ_VFUNCPTR 187 | static void * (* volatile _smz_memset_fptr)(void*,int,size_t) = &memset; 188 | static void secure_memzero(void * ptr, size_t len) { 189 | _smz_memset_fptr(ptr, 0, len); 190 | } 191 | 192 | #endif 193 | 194 | #endif // _SECURE_MEMZERO_H_ 195 | -------------------------------------------------------------------------------- /m4/ax_boost_base.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_boost_base.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for the Boost C++ libraries of a particular version (or newer) 12 | # 13 | # If no path to the installed boost library is given the macro searchs 14 | # under /usr, /usr/local, /opt and /opt/local and evaluates the 15 | # $BOOST_ROOT environment variable. Further documentation is available at 16 | # . 17 | # 18 | # This macro calls: 19 | # 20 | # AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) 21 | # 22 | # And sets: 23 | # 24 | # HAVE_BOOST 25 | # 26 | # LICENSE 27 | # 28 | # Copyright (c) 2008 Thomas Porschberg 29 | # Copyright (c) 2009 Peter Adolphs 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. This file is offered as-is, without any 34 | # warranty. 35 | 36 | #serial 23 37 | 38 | AC_DEFUN([AX_BOOST_BASE], 39 | [ 40 | AC_ARG_WITH([boost], 41 | [AS_HELP_STRING([--with-boost@<:@=ARG@:>@], 42 | [use Boost library from a standard location (ARG=yes), 43 | from the specified location (ARG=), 44 | or disable it (ARG=no) 45 | @<:@ARG=yes@:>@ ])], 46 | [ 47 | if test "$withval" = "no"; then 48 | want_boost="no" 49 | elif test "$withval" = "yes"; then 50 | want_boost="yes" 51 | ac_boost_path="" 52 | else 53 | want_boost="yes" 54 | ac_boost_path="$withval" 55 | fi 56 | ], 57 | [want_boost="yes"]) 58 | 59 | 60 | AC_ARG_WITH([boost-libdir], 61 | AS_HELP_STRING([--with-boost-libdir=LIB_DIR], 62 | [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), 63 | [ 64 | if test -d "$withval" 65 | then 66 | ac_boost_lib_path="$withval" 67 | else 68 | AC_MSG_ERROR(--with-boost-libdir expected directory name) 69 | fi 70 | ], 71 | [ac_boost_lib_path=""] 72 | ) 73 | 74 | if test "x$want_boost" = "xyes"; then 75 | boost_lib_version_req=ifelse([$1], ,1.20.0,$1) 76 | boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` 77 | boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` 78 | boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` 79 | boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` 80 | if test "x$boost_lib_version_req_sub_minor" = "x" ; then 81 | boost_lib_version_req_sub_minor="0" 82 | fi 83 | WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` 84 | AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) 85 | succeeded=no 86 | 87 | dnl On 64-bit systems check for system libraries in both lib64 and lib. 88 | dnl The former is specified by FHS, but e.g. Debian does not adhere to 89 | dnl this (as it rises problems for generic multi-arch support). 90 | dnl The last entry in the list is chosen by default when no libraries 91 | dnl are found, e.g. when only header-only libraries are installed! 92 | libsubdirs="lib" 93 | ax_arch=`uname -m` 94 | case $ax_arch in 95 | x86_64) 96 | libsubdirs="lib64 libx32 lib lib64" 97 | ;; 98 | ppc64|s390x|sparc64|aarch64) 99 | libsubdirs="lib64 lib lib64" 100 | ;; 101 | esac 102 | 103 | dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give 104 | dnl them priority over the other paths since, if libs are found there, they 105 | dnl are almost assuredly the ones desired. 106 | AC_REQUIRE([AC_CANONICAL_HOST]) 107 | libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" 108 | 109 | case ${host_cpu} in 110 | i?86) 111 | libsubdirs="lib/i386-${host_os} $libsubdirs" 112 | ;; 113 | esac 114 | 115 | dnl some arches may advertise a cpu type that doesn't line up with their 116 | dnl prefix's cpu type. For example, uname may report armv7l while libs are 117 | dnl installed to /usr/lib/arm-linux-gnueabihf. Try getting the compiler's 118 | dnl value for an extra chance of finding the correct path. 119 | libsubdirs="lib/`$CXX -dumpmachine 2>/dev/null` $libsubdirs" 120 | 121 | dnl first we check the system location for boost libraries 122 | dnl this location ist chosen if boost libraries are installed with the --layout=system option 123 | dnl or if you install boost with RPM 124 | if test "$ac_boost_path" != ""; then 125 | BOOST_CPPFLAGS="-I$ac_boost_path/include" 126 | for ac_boost_path_tmp in $libsubdirs; do 127 | if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then 128 | BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" 129 | break 130 | fi 131 | done 132 | elif test "$cross_compiling" != yes; then 133 | for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do 134 | if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then 135 | for libsubdir in $libsubdirs ; do 136 | if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 137 | done 138 | BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" 139 | BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" 140 | break; 141 | fi 142 | done 143 | fi 144 | 145 | dnl overwrite ld flags if we have required special directory with 146 | dnl --with-boost-libdir parameter 147 | if test "$ac_boost_lib_path" != ""; then 148 | BOOST_LDFLAGS="-L$ac_boost_lib_path" 149 | fi 150 | 151 | CPPFLAGS_SAVED="$CPPFLAGS" 152 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 153 | export CPPFLAGS 154 | 155 | LDFLAGS_SAVED="$LDFLAGS" 156 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 157 | export LDFLAGS 158 | 159 | AC_REQUIRE([AC_PROG_CXX]) 160 | AC_LANG_PUSH(C++) 161 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 162 | @%:@include 163 | ]], [[ 164 | #if BOOST_VERSION >= $WANT_BOOST_VERSION 165 | // Everything is okay 166 | #else 167 | # error Boost version is too old 168 | #endif 169 | ]])],[ 170 | AC_MSG_RESULT(yes) 171 | succeeded=yes 172 | found_system=yes 173 | ],[: 174 | ]) 175 | AC_LANG_POP([C++]) 176 | 177 | 178 | 179 | dnl if we found no boost with system layout we search for boost libraries 180 | dnl built and installed without the --layout=system option or for a staged(not installed) version 181 | if test "x$succeeded" != "xyes"; then 182 | _version=0 183 | if test "$ac_boost_path" != ""; then 184 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then 185 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do 186 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` 187 | V_CHECK=`expr $_version_tmp \> $_version` 188 | if test "$V_CHECK" = "1" ; then 189 | _version=$_version_tmp 190 | fi 191 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` 192 | BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" 193 | done 194 | fi 195 | else 196 | if test "$cross_compiling" != yes; then 197 | for ac_boost_path in /usr /usr/local /opt /opt/local ; do 198 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then 199 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do 200 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` 201 | V_CHECK=`expr $_version_tmp \> $_version` 202 | if test "$V_CHECK" = "1" ; then 203 | _version=$_version_tmp 204 | best_path=$ac_boost_path 205 | fi 206 | done 207 | fi 208 | done 209 | 210 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` 211 | BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" 212 | if test "$ac_boost_lib_path" = ""; then 213 | for libsubdir in $libsubdirs ; do 214 | if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 215 | done 216 | BOOST_LDFLAGS="-L$best_path/$libsubdir" 217 | fi 218 | fi 219 | 220 | if test "x$BOOST_ROOT" != "x"; then 221 | for libsubdir in $libsubdirs ; do 222 | if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 223 | done 224 | if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then 225 | version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` 226 | stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` 227 | stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` 228 | V_CHECK=`expr $stage_version_shorten \>\= $_version` 229 | if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then 230 | AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) 231 | BOOST_CPPFLAGS="-I$BOOST_ROOT" 232 | BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" 233 | fi 234 | fi 235 | fi 236 | fi 237 | 238 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 239 | export CPPFLAGS 240 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 241 | export LDFLAGS 242 | 243 | AC_LANG_PUSH(C++) 244 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 245 | @%:@include 246 | ]], [[ 247 | #if BOOST_VERSION >= $WANT_BOOST_VERSION 248 | // Everything is okay 249 | #else 250 | # error Boost version is too old 251 | #endif 252 | ]])],[ 253 | AC_MSG_RESULT(yes) 254 | succeeded=yes 255 | found_system=yes 256 | ],[: 257 | ]) 258 | AC_LANG_POP([C++]) 259 | fi 260 | 261 | if test "$succeeded" != "yes" ; then 262 | if test "$_version" = "0" ; then 263 | AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) 264 | else 265 | AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) 266 | fi 267 | # execute ACTION-IF-NOT-FOUND (if present): 268 | ifelse([$3], , :, [$3]) 269 | else 270 | AC_SUBST(BOOST_CPPFLAGS) 271 | AC_SUBST(BOOST_LDFLAGS) 272 | AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) 273 | # execute ACTION-IF-FOUND (if present): 274 | ifelse([$2], , :, [$2]) 275 | fi 276 | 277 | CPPFLAGS="$CPPFLAGS_SAVED" 278 | LDFLAGS="$LDFLAGS_SAVED" 279 | fi 280 | 281 | ]) 282 | -------------------------------------------------------------------------------- /test/egihash_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================ 3 | Name : egihash_test.cpp 4 | Author : Ranjeet Devgun 5 | Version : 6 | Copyright : TODO Copyright notice 7 | Description : Uses shared library to print greeting 8 | To run the resulting executable the LD_LIBRARY_PATH must be 9 | set to ${project_loc}/libegihash/.libs 10 | Alternatively, libtool creates a wrapper shell script in the 11 | build directory of this program which can be used to run it. 12 | Here the script will be called test. 13 | ============================================================================ 14 | */ 15 | 16 | #include 17 | #include 18 | #include "egihash.h" 19 | 20 | #ifdef _WIN32 21 | #include 22 | #include 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define BOOST_TEST_MODULE libegihash_unit_tests 36 | #include 37 | 38 | using namespace std; 39 | using byte = uint8_t; 40 | using bytes = std::vector; 41 | namespace fs = boost::filesystem; 42 | 43 | namespace 44 | { 45 | bool dag_progress(::std::size_t step, ::std::size_t max, int phase) 46 | { 47 | using namespace egihash; 48 | 49 | // saving output for longer running tasks like DAG generation 50 | switch (phase) 51 | { 52 | case cache_saving: 53 | case cache_loading: 54 | case dag_saving: 55 | case dag_loading: 56 | return true; 57 | default: 58 | break; 59 | } 60 | 61 | switch (phase) 62 | { 63 | case cache_seeding: 64 | cout << "\rSeeding cache..."; 65 | break; 66 | case cache_generation: 67 | cout << "\rGenerating cache..."; 68 | break; 69 | case cache_saving: 70 | cout << "\rSaving cache..."; 71 | break; 72 | case cache_loading: 73 | cout << "\rLoading cache..."; 74 | break; 75 | case dag_generation: 76 | cout << "\rGenerating DAG..."; 77 | break; 78 | case dag_saving: 79 | cout << "\rSaving DAG..."; 80 | break; 81 | case dag_loading: 82 | cout << "\rLoading DAG..."; 83 | break; 84 | default: 85 | break; 86 | } 87 | 88 | cout << fixed << setprecision(2) 89 | << static_cast(step) / static_cast(max) * 100.0 << "%" 90 | << setfill(' ') << setw(80) << flush; 91 | 92 | if (step == max) cout << "\r" << endl; 93 | 94 | return true; 95 | }; 96 | 97 | template 98 | void test_hash_func() 99 | { 100 | string filename = string("hashcache_") + std::to_string(HashType::hash_size * 8) + ".csv"; 101 | fs::path hcPath = fs::current_path() / "data" / filename; 102 | #ifdef TEST_DATA_DIR 103 | if (!fs::exists(hcPath)) 104 | { 105 | hcPath = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename; 106 | } 107 | #endif 108 | ifstream hif(hcPath.string().c_str()); 109 | BOOST_REQUIRE_MESSAGE(hif.is_open(), "hash cache missing?"); 110 | if ( hif.is_open() ) 111 | { 112 | char buffer[1024] = {0}; 113 | size_t lineCount = 1; 114 | while(hif.getline(buffer, sizeof(buffer))) 115 | { 116 | string line = buffer; 117 | auto index = line.find_first_of(','); 118 | auto hashSource = line.substr(0, index), hashExpected = line.substr(index + 1); 119 | BOOST_REQUIRE_MESSAGE(hashSource.size() == HashType::hash_size, "\ninvalid hash source at line: " << lineCount); 120 | BOOST_REQUIRE_MESSAGE(hashExpected.size() == (HashType::hash_size * 2), "\ninvalid expected hash entry at line: " << lineCount); 121 | auto actual = HashType(hashSource.c_str(), hashSource.length()).to_hex(); 122 | BOOST_REQUIRE_MESSAGE(hashExpected == actual, "\nsource: " << hashSource << "\nexpected: " << hashExpected.c_str() << "\n" << "actual: " << actual.c_str() << "\n"); 123 | lineCount++; 124 | } 125 | } 126 | } 127 | 128 | egihash::h256_t HashFromHex(std::string const & hex) 129 | { 130 | using namespace egihash; 131 | h256_t ret; 132 | for (size_t i = 0; i < 32; i++) 133 | { 134 | auto const ptr = hex.c_str(); 135 | char hexpair[] = { ptr[i*2], ptr[i*2 + 1] }; 136 | ret.b[i] = static_cast(stoi(hexpair, nullptr, 16)); 137 | } 138 | return ret; 139 | } 140 | } 141 | 142 | BOOST_AUTO_TEST_SUITE(Keccak); 143 | 144 | BOOST_AUTO_TEST_CASE(Keccak_256) 145 | { 146 | test_hash_func(); 147 | } 148 | 149 | BOOST_AUTO_TEST_CASE(Keccak_512) 150 | { 151 | test_hash_func(); 152 | } 153 | 154 | BOOST_AUTO_TEST_SUITE_END(); 155 | 156 | 157 | BOOST_AUTO_TEST_SUITE(Egihash); 158 | 159 | BOOST_AUTO_TEST_CASE(EGIHASH_HASHIMOTO) 160 | { 161 | using namespace std; 162 | using namespace egihash; 163 | 164 | if (!boost::filesystem::exists( "data/egihash.dag" )) 165 | { 166 | egihash::dag_t dag(0, dag_progress); 167 | dag.save("data/egihash.dag"); 168 | } 169 | 170 | dag_t d("data/egihash.dag", dag_progress); 171 | 172 | string rawdata("this is a test string to be hashed"); 173 | std::vector> vExpected = { 174 | std::make_tuple(0x7c7c597c, "e85cb09f99553758a8a794633c93ed25318e2f2839b3a85328e775220ab0a14d", "deafd12b8f35f15b2cac9455ee4f32620cea6727e18e21a81b196633a74d6018") 175 | ,std::make_tuple(0xFFFFFFFF00000000, "c2005aa32d527dcbce043648eb04d818be68c8649d353d29eb3c9d5d15927a25", "b0d1c89335fafb7b8c9591fc58623ddf342977cffec88d8d84f14bbfe6f4f651") 176 | ,std::make_tuple(1234567890, "1e884b98b307fa44e7ba1d015f6fab47303ac41d04638076479421ea91ea633a", "af969a99b8ee5934b9598a646361675c3b7b8783754e011edd9eb9a702c7711a") 177 | }; 178 | 179 | for ( auto const & expected : vExpected ) 180 | { 181 | for(auto i = 0; i < 2; ++i) 182 | { 183 | auto const h = i == 0 ? full::hash(d, h256_t(rawdata.c_str(), rawdata.size()), std::get<0>(expected)) : light::hash(d.get_cache(), h256_t(rawdata.c_str(), rawdata.size()), std::get<0>(expected)); 184 | auto const value_str = h.value.to_hex(); 185 | auto const mix_str = h.mixhash.to_hex(); 186 | BOOST_CHECK_MESSAGE(value_str == std::get<1>(expected), "\nnounce=" << std::get<0>(expected) << "\nactual=" << value_str << "\nexpected=" << std::get<1>(expected)); 187 | BOOST_CHECK_MESSAGE(mix_str == std::get<2>(expected), "\nnounce=" << std::get<0>(expected) << "\nactual=" << mix_str << "\nexpected=" << std::get<2>(expected)); 188 | } 189 | } 190 | 191 | d.unload(); 192 | } 193 | 194 | BOOST_AUTO_TEST_CASE(FULL_CLIENT) 195 | { 196 | string filename_egi = string("egihash.dag"); 197 | string filename_et = string("ethash_eg_seed_2_hashes.dag"); 198 | fs::path egiDagPath = fs::current_path() / "data" / filename_egi; 199 | fs::path etDagPath = fs::current_path() / "data" / filename_et; 200 | 201 | BOOST_ASSERT(16776896 == egihash::cache_t::get_cache_size(0)); 202 | BOOST_ASSERT(1073739904 == egihash::dag_t::get_full_size(0)); 203 | 204 | if ( !boost::filesystem::exists( egiDagPath ) ) 205 | { 206 | egihash::dag_t dag(0, dag_progress); 207 | dag.save(egiDagPath.string()); 208 | } 209 | 210 | // File should be byte by byte same: 211 | ifstream dag_ethash_if(etDagPath.string().c_str(), std::ios_base::binary); 212 | ifstream dag_eghash_if(egiDagPath.string().c_str(), std::ios_base::binary); 213 | BOOST_ASSERT(dag_ethash_if.is_open() && dag_eghash_if.is_open()); 214 | if ( dag_ethash_if.is_open() && dag_eghash_if.is_open() ) 215 | { 216 | uint64_t egiDagSizeSkip = sizeof(egihash::constants::DAG_MAGIC_BYTES) + 217 | sizeof(egihash::constants::MAJOR_VERSION) + 218 | sizeof(egihash::constants::REVISION) + 219 | sizeof(egihash::constants::MINOR_VERSION) + 220 | sizeof(uint64_t) + // epoch 221 | sizeof(uint64_t) + // cache begin 222 | sizeof(uint64_t) + // cache_end 223 | sizeof(uint64_t) + // dag_begin 224 | sizeof(uint64_t);// dag_end 225 | 226 | egiDagSizeSkip += egihash::cache_t::get_cache_size(0); 227 | 228 | constexpr uint32_t BUFFER_SIZE = 32 * 1024 * 1024; 229 | constexpr uint32_t DATA_TO_READ = 1024; 230 | std::unique_ptr buffer_eg (new uint8_t[BUFFER_SIZE]); 231 | std::unique_ptr buffer_et (new uint8_t[BUFFER_SIZE]); 232 | 233 | dag_eghash_if.read(reinterpret_cast(buffer_eg.get()), egiDagSizeSkip); 234 | dag_eghash_if.read(reinterpret_cast(buffer_eg.get()), DATA_TO_READ); 235 | dag_ethash_if.read(reinterpret_cast(buffer_et.get()), DATA_TO_READ); 236 | auto eg_read = dag_eghash_if.gcount(), et_read = dag_ethash_if.gcount(); 237 | BOOST_ASSERT(eg_read == DATA_TO_READ); 238 | BOOST_ASSERT(eg_read == et_read); 239 | BOOST_ASSERT( ( dag_eghash_if.eof() && dag_ethash_if.eof()) || ( !dag_eghash_if.eof()&& !dag_ethash_if.eof() ) ); 240 | BOOST_ASSERT( 0 == ::std::memcmp(buffer_et.get(), buffer_eg.get(), eg_read) ); 241 | } 242 | } 243 | 244 | BOOST_AUTO_TEST_CASE(headerhashes) 245 | { 246 | using namespace std; 247 | using namespace egihash; 248 | 249 | string filename = string("headerhash_test_vectors.csv"); 250 | fs::path hcPath = fs::current_path() / "data" / filename; 251 | #ifdef TEST_DATA_DIR 252 | if (!fs::exists(hcPath)) 253 | { 254 | hcPath = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename; 255 | } 256 | #endif 257 | ifstream hif(hcPath.string().c_str()); 258 | BOOST_REQUIRE_MESSAGE(hif.is_open(), "Can not read data file headerhash_test_vectors.csv"); 259 | 260 | auto tokenize_line = [](std::string const & line) -> std::vector 261 | { 262 | using namespace boost; 263 | std::vector vec; 264 | tokenizer > tk(line, escaped_list_separator('\\', ',', '\"')); 265 | for (tokenizer >::iterator i(tk.begin());i!=tk.end();++i) 266 | { 267 | vec.push_back(*i); 268 | } 269 | return vec; 270 | }; 271 | 272 | if ( hif.is_open() ) 273 | { 274 | string line; 275 | vector caches; 276 | while (getline(hif, line)) 277 | { 278 | //string line = buffer; 279 | auto const tokens = tokenize_line(line); 280 | BOOST_ASSERT(tokens.size() == 5); 281 | auto const epoch = static_cast(stoi(tokens[0].c_str())); 282 | auto const headerhash = HashFromHex(tokens[1]); 283 | auto const nonce = static_cast(stoi(tokens[2].c_str())); 284 | auto const resulthash = HashFromHex(tokens[3]); 285 | auto const mixhash = HashFromHex(tokens[4]); 286 | 287 | auto const cache = cache_t(epoch * constants::EPOCH_LENGTH); 288 | caches.push_back(cache); 289 | 290 | // make sure hex conversion is behaving sensibly 291 | BOOST_REQUIRE_MESSAGE(headerhash.to_hex() == tokens[1], "hash hex conversion failed"); 292 | 293 | result_t expected; 294 | expected.value = resulthash; 295 | expected.mixhash = mixhash; 296 | 297 | result_t const actual = light::hash(cache, headerhash, nonce); 298 | BOOST_CHECK_MESSAGE(resulthash == actual.value, "Hash value comparison failed (expected " << resulthash.to_hex() << " got " << actual.value.to_hex() << ")"); 299 | BOOST_CHECK_MESSAGE(mixhash == actual.mixhash, "Mix hash comparison failed (expected " << mixhash.to_hex() << " got " << actual.mixhash.to_hex() << ")"); 300 | BOOST_CHECK_MESSAGE(expected == actual, "Hash result comparison failed"); 301 | } 302 | for (auto && i: caches) 303 | { 304 | i.unload(); 305 | } 306 | } 307 | } 308 | 309 | BOOST_AUTO_TEST_CASE(seedhash_test) 310 | { 311 | using namespace egihash; 312 | 313 | static constexpr char const * first100_seedhashes[] = 314 | { 315 | "a8494bb2895bd7ed18bb39b7b28af51dec51f7cad330c168f1bd1c90e7614c32", 316 | "0b74b050614361a85afec955c4e276623edc002cce1f3c0aab2f93f34ec7499e", 317 | "714a8ecd802936293b6ad82ba052318ed274874c8f13989809a829237e841892", 318 | "27cb8dbcc45b40addb1e49400b7853f5f6f65776aa23ce6770dce40af5ce355e", 319 | "b8c6d43d85e406c78c6a3d7e4111dd01d6da0b2dcde4939d7fae04b4ef19672e", 320 | "8d39bf554fb2966f40a77625e0bf84f1160a8592d13fed62f5ec45e7002d00e4", 321 | "2683757934f04d6654d8ab6e8ba435e9f143f15e3ab698c3c727b78bc041a58c", 322 | "c7e64cf7742fa4f0c0766b41a2c93d9aafc763d69ba322fc4f0696dd13fa3320", 323 | "7b6035b636b3bc2a2430c43c7a84029f771448ff52b6febe85e232c6f9ca3b64", 324 | "3e6a51fc33b93cb409a7c09b923544a1e3f56e3410cc502ce81c668c95472538", 325 | "cf97dbe1f0017726185ffa98f767b3a5bd8afe810ce98e2d34586b635af5c318", 326 | "610b251d71ab4bc57fad018e20bcdfdb49e74274d80a4063789151f48f27af98", 327 | "f1fb026f5e49cd4b0cb7995568122e08728c31678bf68d745d0c505f848bf454", 328 | "352078c0b7c82eb6c62e2564ed0236d095709fad79847652aa9aff373f7eae97", 329 | "db756caa77d597916a37ecfc3861916ac973b608f403ea3c292442a13e1aa36d", 330 | "05df22f093d80ffaa37f8b37e4f85e93b2feab1cb0bc729f106887f02b7eb86f", 331 | "5fa7a8493a557ef2fcd77049839378a06d571364cee26c1d3d4f80ee2685aa62", 332 | "a900b31d8e3f493a95fa1a731b867e7edd1b2e4bb28ad8ded846e461e744fcd2", 333 | "aa0e8cdf4cf7f99b9a600bcc320bb823de02604cf6df85875a51e9233edec0b2", 334 | "fa56ed28830042113cefa23ee779676731c035e88c501823d2e366b636093039", 335 | "85bc1d7a8ce642984a2f4b351be5dc8ec564a68564c8c6dd77c8f3e9e56d2ec6", 336 | "cfec63c6946587ad0a173f9f94de1e4242408371b0fbeaf25908fec1c57bea38", 337 | "03516ee43138f0f4e263e5576ebb35497e97843a129abc7a14c858f1eee3ad8d", 338 | "2ae5f5db855a2b2fe01237e624a87b8539431680571fed91a0484247c3469dfc", 339 | "4a1937df43af2337408387716bd2260b642a5b1233a342bd069117bf4fd6391c", 340 | "1020c92eb9fbd7e8ed5886dd8bc83b0d9f052129bf17c608ddc128f2c3619a3e", 341 | "d4f2d3d047acffa8385fb9795b2244c0dfeb5e5130d2d730f6e300dfe514de70", 342 | "04eb0f9c600538b16237b7a5bff297c42d1c9e563e522cc9c5bb4ba04c9c810c", 343 | "1c13a1c10fe3e4eccdba90b7bad971f891b42e9b17aca9dc5426e1b85b69c4c2", 344 | "a4858ac4d1f934ee89c22f5bfe6a73ff7e01241c8192391600ed5f1dd8137310", 345 | "d0a73eee47098ba7cd0b421d54ff2eb0524f4b2920b3bf8c22ce321e45b56bf8", 346 | "f4f88ed9fc16303b1bb3d4ce191858ace2ffc6023d67b8637ed3e595f1216cc9", 347 | "06c6e998cef9e1eb1546c7f7db71cdabded80b34143241dd0c07c75e23ae848b", 348 | "ee9ca223b2e94eeaed16d6f80ffa0856d6bf2327ef6e177bc0265b03422da54b", 349 | "8e5b832eae668b4a3d49beceae7259f83b3f2a27c765f703e4acd7dd6f5a929b", 350 | "b802834920f3948e6351d93ebe6937d24ae434ebd5ca6f4d77c192a11dbb66ec", 351 | "d404efa631a6f01eed418c72217e12f911ba5ce611c04d8e6080b0c84b4b6768", 352 | "8b54aabf000c4aa428fe04ea91ed4f6859d68d6867b1480f9510ec70f381654d", 353 | "5268197c54c5ae766c8a490704054563c34a1cb31fa29f7595204ddc6c967c1a", 354 | "ffabd2cf36d56e47f4beb543f10beeda51a5a514b9765d1f5626ae7088536b4f", 355 | "67a27b4bdee84137a42cf6b453cc9ac1ed7223770b9f4fca44ae131013a4fe25", 356 | "9354b15f28a044aad8445eeeb951e6c9519623410ddde28fccd95dfaa1859ce7", 357 | "527cea9d9b4f422377084c1d9e111e695ac7d1b4f387ccc3c556ded69ceb40d0", 358 | "2b106356d7c369b7638e43c01e5d625715faa29d9a4a712a4f0214406f66c18c", 359 | "8010566894b68636a339abb1da0fc058a55b8b6aea7c27f01de867ada1ec8033", 360 | "d7b42b35d36c2c65c240a8197433acdf103bf004aa0d130bd42635800f298d1a", 361 | "a358ba41cf3a869e03af5a89b96d9b09f48f1eccd80ff24c90e8209371a9fcf1", 362 | "3fbeb365f091a104895e63db022f1ffe8bcc2e77d3b6517d3b6419ace972949c", 363 | "0a10fa3d5a7fc763c3dc949f4447289a4a083a0f9f12beca03d3893636dc6b11", 364 | "1dd7c5ac509da0050ff16805a6c8bb42cf26dbac25aded19ec5bd8edc9c905de", 365 | "5c61be74641b9e229ca83bd8e240d89d44a2725f0797d90251212cc12dcc21f6", 366 | "1f0ea81f20b517a863c3dd242662d5e22976239412d4b549c4afd52d608b5576", 367 | "135e220b875e3427b6b1fc776e099b2d7a9d86a6ebe96a03196cdbdae3f0d223", 368 | "d185ef051cc7277eded1e13b69c11e7c8c6ce92ab5580a1f4ad17c6701779271", 369 | "fc62b4b8b025e32a74803f1c1523c938aeea3c683029fb1d77656a6deceda542", 370 | "81411dee455ce6f3eaa774f252651fd21b229ff7c078d2ad7af7bf5faf935b20", 371 | "86cab7dbf05587e90849803a4a65cdfe157afdb0c354a30531daea67ec4ad851", 372 | "89d28e735e7aae22c8666e259c67a609bf0eb3fd3a7b336fe7e85be4a0344e1f", 373 | "6b661ea3e2d4e646daddf30ffc5ea0fbd72147f191657caed6b79abdab547238", 374 | "3e6726fc6df9db16a451286ed7c4f38b650d555773573257d02a785e859d0206", 375 | "e454b470a306d1783c3b102981a2c81a0c23ebb507f1239e138b7994730c4974", 376 | "e9eedbc79afd1e51d5b17befaa3c1cc98dfb0557465c8c323c958b57a79c7cde", 377 | "c9c2448c809fa3e4fad3f98c24ee36e90fe56577a5ef8067e13defd26b0c4830", 378 | "524189a22dc5ac47453088f691ef0a56a57713ed469ca1e8c6bee92878960f69", 379 | "c465fa0f490b7409758797d2b24ace35c139813aea48b74ea713dd709641bcf1", 380 | "76a3b1da2f636307513f3ea010cf5eef9febf571fa58b0b4f9b85dcac3bfed69", 381 | "e49d7dbd4e1f4182af5e7f7c1e1f8e8e3b6fd87b9eca7b4593e1e669d770071a", 382 | "2c3e099519a2e5e428048343388296457ec4f7ab2855cfe1d2caafaa5ea28026", 383 | "e442fdd0732989b0e800579fd957dfd8c9273d28be445c9f661ed93e973767f6", 384 | "88e49c49a360339187b0d51d11bb424a936c23cee0d425c0bac454393ad798f2", 385 | "0821473fd962930889a15684faba9476ad53643cc8b02376a79e69f826f27a55", 386 | "a367ffbeb0f3581b5cc31d1f1e202957ee741242d374c1cdbf90c15c5a0b7ba1", 387 | "e0ff5135e68d3a2e7e83099ef8a77d6cae2843da5824d24834123d44fbfe42c3", 388 | "2b182261fa701802f80777e82ed26c12b295db0f9d4c38be9602620863e402fb", 389 | "454484a49ebc2af66431959220f46483f7a848e10fc1136f3b17c56b18bea438", 390 | "50febe095d685750f0e8191297d3b4def34fd9124897edbd2233834bb7e5d059", 391 | "1f2c414d30d5b278617e8fb5cad563b5a64f4d3aa43601cb0148b683e6e74b99", 392 | "04b52d092cecf05f52b7c2baf22882b0bca8baa243a09edb547dd44ec52b68ae", 393 | "3b39138f70c009da8121cf88b0431fb3327446b37ada66e2d7e493f3a648a5c0", 394 | "91e6db67e039647c9d74abeeac7a4f60714632e035893abddd81f449ca75524a", 395 | "ce5e355929e5f16affa2345c9c36ba83d63bc90850d3c265ed69a83a5f5aea26", 396 | "6a934e0d79a49439a329412793a00b2e5226da793115be2e4440b002a6de60c9", 397 | "4b31566354b1f8a694c7c7c7893070ef94ba184254128d0d58bd0acc866d9b2a", 398 | "6e2ceac1b4ba7dc3e4eb8544ca3d1a83d9f6339840534374099b30e8f9b3792a", 399 | "c85a807871ad72bae6fa9e404d7e6ca3416bb4283719d08a0b7f721a6930d814", 400 | "54d1d677e18d68c6dd7c210c819b598f0bd23a6c258b61ae4a47d9491b60c6ba", 401 | "9623ca38fa26d375a22a859b63d909cf512440e079395b9f2dc3e7921ad1680b", 402 | "ba20a83b57aa9ef2331f3beead8189e1cc199250dfb669ee8af11e946457dad2", 403 | "af99256d9b334b0d19cb77546f150ecc20ab47b2575b5c9ad344822f5d54c1de", 404 | "1c2800186fece92e35f0c9c455ad95cee9aa81c28be1f683c793c0673760939b", 405 | "63bde9e1a825e7abaafc53b9493c59a7e14e571334389b5e7a4e06a2ca6e4d48", 406 | "ab954e6c4cc6f48880772d5257db79beff4488a7c084a3d023f47f427e152682", 407 | "9141c1f8393351776de7f07385d7f810af79e9358f75558a6045bfab81ec20a5", 408 | "f788ac17949d05847c93d9fb15d4cfc59e98b0fe3a071027729b7847b0f06cb6", 409 | "0d0e825f1668883554e8d21e74f1433380ca8e240e949e5f34b14f6b5680f182", 410 | "b01eb592029671e00f0628f34549c85c59cf33e5a8c72758d95cdbf4b00f08bb", 411 | "3be8472c70181c48172d304d6242356e1711d21db61f7afdced3795b393a050f", 412 | "5f4dd21e1e604e7844a11a7a94681d744d78f6454966820c5f7ae67159865a2b", 413 | "dd41a07051a88b82db7c313454924d9b5221c8ba3ea8f2e6209354f7fa235dbf", 414 | "e4101f3e107b7f810b2b81101a148797701a82320497d0240c8a43a7aa18bf8f" 415 | }; 416 | 417 | // test the first 100 epochs worth of seedhashes 418 | for (size_t i = 0; i < 100; i++) 419 | { 420 | BOOST_ASSERT(cache_t::get_seedhash(i * constants::EPOCH_LENGTH).to_hex() == std::string(first100_seedhashes[i])); 421 | } 422 | 423 | // test that all block numbers up to the first EPOCH_LENGTH return the first epoch seedhash 424 | auto const first_hash = std::string(first100_seedhashes[0]); 425 | for (size_t i = 0; i < constants::EPOCH_LENGTH; i++) 426 | { 427 | BOOST_ASSERT(cache_t::get_seedhash(i).to_hex() == first_hash); 428 | } 429 | 430 | // test that all block numbers from the second EPOCH_LENGTH to the third epoch return the second epoch seedhash 431 | auto const second_hash = std::string(first100_seedhashes[1]); 432 | for (size_t i = constants::EPOCH_LENGTH; i < (constants::EPOCH_LENGTH + constants::EPOCH_LENGTH); i++) 433 | { 434 | BOOST_ASSERT(cache_t::get_seedhash(i).to_hex() == second_hash); 435 | } 436 | } 437 | 438 | // test that light hashes and full hashes produce the same values 439 | BOOST_AUTO_TEST_CASE(light_hash_vs_full_hash_comparison) 440 | { 441 | using namespace std; 442 | using namespace egihash; 443 | 444 | if (!boost::filesystem::exists( "data/egihash.dag" )) 445 | { 446 | egihash::dag_t dag(0, dag_progress); 447 | dag.save("data/egihash.dag"); 448 | } 449 | 450 | dag_t d("data/egihash.dag", dag_progress); 451 | cache_t c(d.get_cache()); 452 | 453 | string rawdata("this is a test string to be hashed"); 454 | h256_t firsthash(rawdata.c_str(), rawdata.size()); 455 | 456 | for (size_t i = 0; i < 1000; i++) 457 | { 458 | uint64_t nonce = (*reinterpret_cast(&firsthash.b[0])) ^ (*reinterpret_cast(&firsthash.b[16])); 459 | firsthash = h256_t(&firsthash.b[0], firsthash.hash_size); 460 | auto const lighthash = light::hash(c, firsthash, nonce); 461 | auto const fullhash = full::hash(d, firsthash, nonce); 462 | 463 | // check that the hashes are nonempty 464 | BOOST_ASSERT(lighthash); 465 | BOOST_ASSERT(fullhash); 466 | 467 | // check the byte for byte value and the mixhash is the same for both light and full hashes 468 | BOOST_ASSERT(memcmp(&lighthash.value.b[0], &fullhash.value.b[0], (std::min)(lighthash.value.hash_size, fullhash.value.hash_size)) == 0); 469 | BOOST_ASSERT(memcmp(&lighthash.mixhash.b[0], &fullhash.mixhash.b[0], (std::min)(lighthash.value.hash_size, fullhash.value.hash_size)) == 0); 470 | 471 | // checks operator== for egihash::h256_t 472 | BOOST_ASSERT(lighthash.value == fullhash.value); 473 | BOOST_ASSERT(lighthash.mixhash == fullhash.mixhash); 474 | 475 | // checks operator== for egihash::result_t 476 | BOOST_ASSERT(lighthash == fullhash); 477 | } 478 | 479 | d.unload(); 480 | } 481 | 482 | // test loading from the the dag cache as well as unloading 483 | BOOST_AUTO_TEST_CASE(dag_cache) 484 | { 485 | using namespace std; 486 | using namespace egihash; 487 | 488 | BOOST_REQUIRE_MESSAGE(boost::filesystem::exists("data/egihash.dag"), "DAG file not generated yet. Please re-run test case."); 489 | 490 | dag_t d1("data/egihash.dag", dag_progress); 491 | 492 | bool success = true; 493 | auto already_loaded = [&success](::std::size_t /*step*/, ::std::size_t /*max*/, int /*phase*/) -> bool 494 | { 495 | // if we have to load, we already failed because this dag should be loaded 496 | success = false; 497 | return false; 498 | }; 499 | 500 | // ensure we don't try to load a DAG again when it is already loaded 501 | dag_t d2("data/egihash.dag", already_loaded); 502 | try 503 | { 504 | BOOST_REQUIRE_MESSAGE(success, "Attempt to re-load already loaded DAG - should be retrieved from DAG cache"); 505 | } 506 | catch (hash_exception const &) 507 | { 508 | // ignored exception - we cancelled loading so we expect this 509 | } 510 | BOOST_ASSERT(dag_t::is_loaded(0)); 511 | BOOST_ASSERT(dag_t::get_loaded().size() == 1); 512 | d1.unload(); 513 | BOOST_ASSERT(!dag_t::is_loaded(0)); 514 | BOOST_ASSERT(dag_t::get_loaded().size() == 0); 515 | success=false; 516 | 517 | // ensure that after unloading, we would require re-loading this DAG 518 | auto not_loaded = [&success](::std::size_t /*step*/, ::std::size_t /*max*/, int /*phase*/) -> bool 519 | { 520 | success = true; 521 | return false; 522 | }; 523 | try 524 | { 525 | dag_t d3("data/egihash.dag", not_loaded); 526 | BOOST_REQUIRE_MESSAGE(success, "Unloaded DAG was not re-loaded correctly"); 527 | } 528 | catch (hash_exception const &) 529 | { 530 | // ignored exception - we cancelled loading so we expect this 531 | } 532 | BOOST_ASSERT(!dag_t::is_loaded(0)); 533 | BOOST_ASSERT(dag_t::get_loaded().size() == 0); 534 | BOOST_ASSERT(success); 535 | } 536 | 537 | // test loading from the the cache cache as well as unloading 538 | BOOST_AUTO_TEST_CASE(cache_cache) 539 | { 540 | using namespace std; 541 | using namespace egihash; 542 | 543 | cache_t c1(0, dag_progress); 544 | 545 | bool success = true; 546 | auto already_loaded = [&success](::std::size_t /*step*/, ::std::size_t /*max*/, int /*phase*/) -> bool 547 | { 548 | // if we have to load, we already failed because this dag should be loaded 549 | success = false; 550 | return false; 551 | }; 552 | 553 | // ensure we don't try to load a cache again when it is already loaded 554 | cache_t c2(0, already_loaded); 555 | try 556 | { 557 | BOOST_REQUIRE_MESSAGE(success, "Attempt to re-load already loaded cache_t - should be retrieved from cache cache"); 558 | } 559 | catch (hash_exception const &) 560 | { 561 | // ignored exception - we cancelled loading so we expect this 562 | } 563 | BOOST_ASSERT(cache_t::is_loaded(0)); 564 | BOOST_ASSERT(cache_t::get_loaded().size() == 1); 565 | c1.unload(); 566 | BOOST_ASSERT(!cache_t::is_loaded(0)); 567 | BOOST_ASSERT(cache_t::get_loaded().size() == 0); 568 | success=false; 569 | 570 | // ensure that after unloading, we would require re-loading this DAG 571 | auto not_loaded = [&success](::std::size_t /*step*/, ::std::size_t /*max*/, int /*phase*/) -> bool 572 | { 573 | success = true; 574 | return false; 575 | }; 576 | try 577 | { 578 | cache_t c3(0, not_loaded); 579 | BOOST_REQUIRE_MESSAGE(success, "Unloaded DAG was not re-loaded correctly"); 580 | } 581 | catch (hash_exception const &) 582 | { 583 | // ignored exception - we cancelled loading so we expect this 584 | } 585 | BOOST_ASSERT(!cache_t::is_loaded(0)); 586 | BOOST_ASSERT(cache_t::get_loaded().size() == 0); 587 | BOOST_ASSERT(success); 588 | } 589 | 590 | BOOST_AUTO_TEST_SUITE_END(); 591 | -------------------------------------------------------------------------------- /include/egihash.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ryan Lucchese 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #ifdef __cplusplus 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace egihash 19 | { 20 | bool test_function() noexcept; 21 | 22 | namespace constants 23 | { 24 | /** \brief DAG_MAGIC_BYTES is the starting sequence of a DAG file, used for identification. 25 | */ 26 | static constexpr char DAG_MAGIC_BYTES[] = "EGIHASH_DAG"; 27 | 28 | /** \brief DAG_FILE_HEADER_SIZE is the expected size of a DAG file header. 29 | */ 30 | static constexpr uint32_t DAG_FILE_HEADER_SIZE = 64u; 31 | 32 | /** \brief DAG_FILE_MINIMUM_SIZE is the size of the DAG file at epoch 0. 33 | */ 34 | static constexpr uint64_t DAG_FILE_MINIMUM_SIZE = 1090516864; 35 | 36 | /** \brief CALLBACK_FREQUENCY determines how often callbacks will be called. 37 | * 38 | * 1 means every iteration, 10 means every 10th iteration, and so on... 39 | */ 40 | static constexpr uint32_t CALLBACK_FREQUENCY = 1024u; 41 | 42 | /** \brief The major version of egihash 43 | */ 44 | static constexpr uint32_t MAJOR_VERSION = 1u; 45 | 46 | /** \brief The revision number (middle version digit) of egihash 47 | */ 48 | static constexpr uint32_t REVISION = 23u; 49 | 50 | /** \brief The minor version number of egihash 51 | */ 52 | static constexpr uint32_t MINOR_VERSION = 0u; 53 | 54 | /** \brief Number of bytes in a hash word. 55 | */ 56 | static constexpr uint32_t WORD_BYTES = 4u; 57 | 58 | /** \brief The number of bytes in the dataset at genesis. 59 | */ 60 | static constexpr uint32_t DATASET_BYTES_INIT = 1u << 30u; 61 | 62 | /** \brief The growth of the dataset in bytes per epoch. 63 | */ 64 | static constexpr uint32_t DATASET_BYTES_GROWTH = 1u << 23u; 65 | 66 | /** \brief The number of bytes in the cache at genesis. 67 | */ 68 | static constexpr uint32_t CACHE_BYTES_INIT = 1u << 24u; 69 | 70 | /** \brief The growth of the cache in bytes per epoch. 71 | */ 72 | static constexpr uint32_t CACHE_BYTES_GROWTH = 1u << 17u; 73 | 74 | /** \brief Ratio of the size of the DAG in bytes relative to the size of the cache in bytes.. 75 | */ 76 | static constexpr uint32_t CACHE_MULTIPLIER=1024u; 77 | 78 | /** \brief The number of blocks which constitute one epoch. 79 | * 80 | * The DAG and cache must be regenerated once per epoch. 81 | */ 82 | static constexpr uint32_t EPOCH_LENGTH = 30000u; 83 | 84 | /** \brief The width of the mix hash for egihash. 85 | */ 86 | static constexpr uint32_t MIX_BYTES = 128u; 87 | 88 | /** \brief The size of an egihash in bytes. 89 | */ 90 | static constexpr uint32_t HASH_BYTES = 64u; 91 | 92 | /** \brief The number of parents for each element in the DAG. 93 | */ 94 | static constexpr uint32_t DATASET_PARENTS = 256u; 95 | 96 | /** \brief The number of hashing rounds used to produce the cache. 97 | */ 98 | static constexpr uint32_t CACHE_ROUNDS = 3u; 99 | 100 | /** \brief The number of DAG lookups to compute an egihash. 101 | */ 102 | static constexpr uint32_t ACCESSES = 64u; 103 | } 104 | 105 | /** \brief node union is used instead of the native integer to allow both bytes level access and as a 4 byte hash word 106 | * 107 | */ 108 | #pragma pack(push, 1) 109 | union node 110 | { 111 | uint32_t hword; 112 | uint8_t bytes[4]; 113 | node() 114 | :hword{} 115 | {} 116 | 117 | node(uint8_t bytes_[4]) 118 | { 119 | ::memcpy(bytes, bytes_, 4); 120 | } 121 | 122 | node(uint32_t hword_):hword(hword_) 123 | {} 124 | }; 125 | #pragma pack(pop) 126 | static_assert(sizeof(node) == sizeof(uint32_t), "Invalid hash node size"); 127 | 128 | 129 | /** \brief hash_exception indicates an error or cancellation when performing a task within egihash. 130 | * 131 | * All functions not marked noexcept may be assumed to throw hash_exception or C++ runtime exceptions. 132 | */ 133 | class hash_exception : public ::std::runtime_error 134 | { 135 | public: 136 | /** \brief construct a hash_exception from a std::string const & 137 | */ 138 | hash_exception(std::string const & what_arg) noexcept 139 | : runtime_error(what_arg) 140 | { 141 | 142 | } 143 | 144 | /** \brief construct a hash_exception from a char const * 145 | */ 146 | hash_exception(char const * what_arg) noexcept 147 | : runtime_error(what_arg) 148 | { 149 | 150 | } 151 | }; 152 | 153 | /** \brief epoch0_seedhash is is the seed hash for the genesis block and first epoch of the DAG. 154 | * All seed hashes for subsequent epochs will be generated from this seedhash. 155 | * 156 | * This represents a keccak-256 hash that will be used as input for building the DAG/cache. 157 | */ 158 | static constexpr char epoch0_seedhash[] = "\xa8\x49\x4b\xb2\x89\x5b\xd7\xed\x18\xbb\x39\xb7\xb2\x8a\xf5\x1d\xec\x51\xf7\xca\xd3\x30\xc1\x68\xf1\xbd\x1c\x90\xe7\x61\x4c\x32"; 159 | static constexpr uint8_t size_epoch0_seedhash = sizeof(epoch0_seedhash) - 1; 160 | static_assert(size_epoch0_seedhash == 32, "Invalid seedhash"); 161 | 162 | /** \brief h256_t represents a the result of a keccak-256 hash. 163 | */ 164 | struct h256_t 165 | { 166 | using size_type = ::std::size_t; 167 | static constexpr size_type hash_size = 32; 168 | 169 | /** \brief Default constructor for h256_t fills data field b with 0 bytes 170 | */ 171 | constexpr h256_t(): b{0} {} 172 | 173 | /** \brief Default copy constructor 174 | */ 175 | h256_t(h256_t const &) = default; 176 | 177 | /** \brief Default copy assignment operator 178 | */ 179 | h256_t & operator=(h256_t const &) = default; 180 | 181 | /** \brief Default move constructor 182 | */ 183 | h256_t(h256_t &&) = default; 184 | 185 | /** \brief Default move assignment operator 186 | */ 187 | h256_t & operator=(h256_t &&) = default; 188 | 189 | /** \brief Default destructor 190 | */ 191 | ~h256_t() = default; 192 | 193 | /** \brief Construct and compute a hash from a data source. 194 | * 195 | * \param input_data A pointer to the start of the data to be hashed 196 | * \param input_size The number of bytes of input data to hash 197 | * \throws hash_exception on error 198 | */ 199 | h256_t(void const * input_data, size_type input_size); 200 | 201 | /** \brief Get the hex-encoded value for this h256_t. 202 | * 203 | * \returns std::string containing hex encoded value for this h256_t. 204 | */ 205 | ::std::string to_hex() const; 206 | 207 | /** \brief Test if this hash is valid. Returns true if hash data is not all 0 bytes. 208 | */ 209 | operator bool() const; 210 | 211 | /** \brief Compare this h256_t to another h256_t. 212 | * 213 | * \return true if the hashes are equal. 214 | */ 215 | bool operator==(h256_t const &) const; 216 | 217 | /** \brief This member stores the 256-bit hash data 218 | */ 219 | uint8_t b[hash_size]; 220 | }; 221 | 222 | /** \brief A default constructed h256_t has all empty bytes. 223 | */ 224 | static constexpr h256_t empty_h256; 225 | 226 | /** \brief h512_t represents a the result of a keccak-512 hash. 227 | */ 228 | struct h512_t 229 | { 230 | using size_type = ::std::size_t; 231 | static constexpr size_type hash_size = 64; 232 | 233 | /** \brief Default constructor for h512_t fills data field b with 0 bytes 234 | */ 235 | constexpr h512_t(): b{0} {} 236 | 237 | /** \brief Default copy constructor 238 | */ 239 | h512_t(h512_t const &) = default; 240 | 241 | /** \brief Default copy assignment operator 242 | */ 243 | h512_t & operator=(h512_t const &) = default; 244 | 245 | /** \brief Default move constructor 246 | */ 247 | h512_t(h512_t &&) = default; 248 | 249 | /** \brief Default move assignment operator 250 | */ 251 | h512_t & operator=(h512_t &&) = default; 252 | 253 | /** \brief Default destructor 254 | */ 255 | ~h512_t() = default; 256 | 257 | /** \brief Construct and compute a hash from a data source. 258 | * 259 | * \param input_data A pointer to the start of the data to be hashed 260 | * \param input_size The number of bytes of input data to hash 261 | * \throws hash_exception on error 262 | */ 263 | h512_t(void const * input_data, size_type input_size); 264 | 265 | /** \brief Get the hex-encoded value for this h512_t. 266 | * 267 | * \returns std::string containing hex encoded value for this h512_t. 268 | */ 269 | ::std::string to_hex() const; 270 | 271 | /** \brief Test if this hash is valid. Returns true if hash data is not all 0 bytes. 272 | */ 273 | operator bool() const; 274 | 275 | /** \brief Compare this h512_t to another h512_t. 276 | * 277 | * \return true if the hashes are equal. 278 | */ 279 | bool operator==(h512_t const &) const; 280 | 281 | /** \brief This member stores the 512-bit hash data 282 | */ 283 | uint8_t b[hash_size]; 284 | }; 285 | 286 | /** \brief A default constructed h512_t has all empty bytes. 287 | */ 288 | static constexpr h512_t empty_h512; 289 | 290 | /** \brief result_t represents the result of an egihash. 291 | */ 292 | struct result_t 293 | { 294 | /** \brief Default constructor 295 | */ 296 | constexpr result_t() = default; 297 | 298 | /** \brief Default copy constructor 299 | */ 300 | result_t(result_t const &) = default; 301 | 302 | /** \brief Default copy assignment operator 303 | */ 304 | result_t & operator=(result_t const &) = default; 305 | 306 | /** \brief Default move constructor 307 | */ 308 | result_t(result_t &&) = default; 309 | 310 | /** \brief Default move assignment operator 311 | */ 312 | result_t & operator=(result_t &&) = default; 313 | 314 | /** \brief Default destructor 315 | */ 316 | ~result_t() = default; 317 | 318 | /** \brief Test if this hash is valid. Returs true of hash data is not all 0 bytes. 319 | */ 320 | operator bool() const; 321 | 322 | /** \brief Compare this result_t to another result_t. 323 | * 324 | * \return true if both the value and mixhash are equal. 325 | */ 326 | bool operator==(result_t const &) const; 327 | 328 | /** \brief This member contains the egihash result value. 329 | */ 330 | h256_t value; 331 | 332 | /** \brief This member contains the mix hash to produce this result. 333 | */ 334 | h256_t mixhash; 335 | }; 336 | 337 | /** \brief A default constructed result_t has all empty bytes. 338 | */ 339 | static constexpr result_t empty_result; 340 | 341 | /** \brief progress_callback_phase values represent different stages at which a progress callback may be called. 342 | */ 343 | enum progress_callback_phase 344 | { 345 | cache_seeding, /**< cache_seeding means fill the cache with hashes of seed hashes: { cache_0 = seedhash; cache_n = keccak512(cache_n-1) } */ 346 | cache_generation, /**< cache_generation is performed with a memory hard hashing function of a seeded cache */ 347 | cache_saving, /**< cache_saving is saving the cache to disk */ 348 | cache_loading, /**< cache_loading is loading the cache from disk */ 349 | dag_generation, /**< dag_generation is computing the DAG for a given epoch (block_number) */ 350 | dag_saving, /**< dag_saving is saving the DAG to disk */ 351 | dag_loading /**< dag_loading is loading the DAG from disk */ 352 | }; 353 | 354 | /** \brief progress_callback_type is a function which may be passed to any phase of DAG/cache or generation to receive progress updates. 355 | * 356 | * \param step is the count of the step just compeleted before this call of the callback. 357 | * \param max is the maximum number of steps that will be performed for this progress_callback_phase. 358 | * \param phase the progress_callback_phase indicating what is being computed at the time of the callback. 359 | * \return false to cancel whatever action is being performed, true to continue. 360 | */ 361 | using progress_callback_type = ::std::function; 362 | 363 | /** \brief read_function_type is a function which passed to various objects which perform loading of a file, such as the cache and DAG. 364 | * 365 | * Note that this function will own whatever data it needs to perform the read, i.e. the filestream. 366 | * \param dst points to the memory location that should be read into. 367 | * \param count represents the number of bytes to read. 368 | * \throws hash_exception if the read failed 369 | */ 370 | using read_function_type = ::std::function; 371 | 372 | /** \brief cache_t is the cache used to compute a DAG for a given epoch. 373 | * 374 | * Each DAG owns a cache_t and the size of the cache grows linearly in time. 375 | */ 376 | struct cache_t 377 | { 378 | /** \brief size_type represents sizes used by a cache. 379 | */ 380 | using size_type = uint64_t; 381 | 382 | /** \brief data_type is the underlying data store which stores a cache. 383 | */ 384 | using data_type = ::std::vector<::std::vector>; 385 | 386 | /** \brief default copy constructor. 387 | */ 388 | cache_t(const cache_t &) = default; 389 | 390 | /** \brief default copy assignment operator. 391 | */ 392 | cache_t & operator=(cache_t const &) = default; 393 | 394 | /** \brief default move constructor. 395 | */ 396 | cache_t(cache_t &&) = default; 397 | 398 | /** \brief default move assignment operator. 399 | */ 400 | cache_t & operator=(cache_t &&) = default; 401 | 402 | /** \brief default destructor. 403 | */ 404 | ~cache_t() = default; 405 | 406 | /** \brief explicitly deleted default constructor. 407 | */ 408 | cache_t() = delete; 409 | 410 | /** \brief Construct a cache_t given a block number and a progress callback function. 411 | * 412 | * \param block_number is the block number for which this cache_t is to be constructed. 413 | * \param callback (optional) may be used to monitor the progress of cache generation. Return false to cancel, true to continue. 414 | */ 415 | cache_t(uint64_t block_number, progress_callback_type callback = [](size_type, size_type, int){ return true; }); 416 | 417 | /** \brief Get the epoch number for which this cache is valid. 418 | * 419 | * \returns uint64_t representing the epoch number (block_number / constants::EPOCH_LENGTH) 420 | */ 421 | uint64_t epoch() const; 422 | 423 | /** \brief Get the size of the cache data in bytes. 424 | * 425 | * \returns size_type representing the size of the cache data in bytes. 426 | */ 427 | size_type size() const; 428 | 429 | /** \brief Get the data the cache contains. 430 | * 431 | * \returns data_type const & to the actual cache data. 432 | */ 433 | data_type const & data() const; 434 | 435 | /** \brief Get the seedhash for this cache. 436 | * 437 | * /returns h256_t seed hash for this cache. 438 | */ 439 | h256_t seedhash() const; 440 | 441 | /** \brief Unload cache. 442 | * 443 | * To actually free a cache from memory, call this function on a cache. 444 | * The cache will then be released from the internal cache. 445 | * Once all references to the cache for this epoch are destroyed, it will be freed. 446 | */ 447 | void unload() const; 448 | 449 | /** \brief Get the size of the cache data in bytes. 450 | * 451 | * \param block_number is the block number for which cache size to compute. 452 | * \returns size_type representing the size of the cache data in bytes. 453 | */ 454 | static size_type get_cache_size(uint64_t const block_number) noexcept; 455 | 456 | /** \brief get_seedhash(uint64_t) will compute the seedhash for a given block number. 457 | * 458 | * \param block_number An unsigned 64-bit integer representing the block number for which to compute the seed hash. 459 | * \return An h256_t keccak-256 seed hash for the given block number. 460 | */ 461 | static h256_t get_seedhash(uint64_t const block_number); 462 | 463 | /** \brief Determine whether the cache_t for this epoch is already loaded 464 | * 465 | * \param epoch is the epoch number for which to determine if a cache_t is already loaded. 466 | * \return bool true if we have this cache_t epoch loaded, false otherwise. 467 | */ 468 | static bool is_loaded(uint64_t const epoch); 469 | 470 | /** \brief Get the epoch numbers for which we already have a cache_t loaded. 471 | * 472 | * \return ::std::vector containing epoch numbers for cache_t's that are already loaded. 473 | */ 474 | static ::std::vector get_loaded(); 475 | 476 | /** \brief cache_t internal implementation. 477 | */ 478 | struct impl_t; 479 | 480 | private: 481 | friend struct dag_t; 482 | 483 | /** \brief Construct a cache_t by loading from disk. 484 | * 485 | * \param epoch is the number of the epoch for the cache we are loading. 486 | * \param size is the size in bytes of the cache we are loading. 487 | * \param read A function which will read cache data from disk. 488 | * \param callback (optional) may be used to monitor the progress of cache loading. Return false to cancel, true to continue. 489 | */ 490 | cache_t(uint64_t epoch, uint64_t size, read_function_type read, progress_callback_type callback = [](size_type, size_type, int){ return true; }); 491 | 492 | /** \brief Load a cache from disk. 493 | * 494 | * \param read A function which will read cache data from disk. 495 | * \param callback (optional) may be used to monitor the progress of cache loading. Return false to cancel, true to continue. 496 | */ 497 | void load(read_function_type read, progress_callback_type callback = [](size_type, size_type, int){ return true; }); 498 | 499 | /** \brief shared_ptr to impl allows default moving/copying of cache. Internally, only one cache_t::impl_t per epoch will exist. 500 | */ 501 | ::std::shared_ptr impl; 502 | }; 503 | 504 | /** \brief dag_t is the DAG which is used by full nodes and miners to compute egihashes. 505 | * 506 | * The DAG gives egihash it's ASIC resistance, ensuring that this hashing function is memory bound not compute bound. 507 | * The DAG must be updated once per constants::EPOCH_LENGTH block numbers. 508 | * The DAG for epoch 0 is 1073739904 bytes in size and will grow linearly with each following epoch. 509 | * The DAG can take a long time to generate. It is recommended to save the DAG to disk to avoid having to regenerate it each time. 510 | * It makes sense to pre-compute the DAG for the next epoch, so generating it does not interrupt mining / operation of a full node. 511 | * Whether by generation or by loading, the DAG will own a cache_t which corresponds to cache for the same epoch. 512 | */ 513 | struct dag_t 514 | { 515 | /** \brief size_type represents sizes used by a cache. 516 | */ 517 | using size_type = ::std::size_t; 518 | 519 | /** \brief data_type is the underlying data store which stores a cache. 520 | */ 521 | using data_type = ::std::vector<::std::vector>; 522 | 523 | /** \brief default copy constructor. 524 | */ 525 | dag_t(dag_t const &) = default; 526 | 527 | /** \brief default copy assignment operator. 528 | */ 529 | dag_t & operator=(dag_t const &) = default; 530 | 531 | /** \brief default move constructor. 532 | */ 533 | dag_t(dag_t &&) = default; 534 | 535 | /** \brief default move assignment operator. 536 | */ 537 | dag_t & operator=(dag_t &&) = default; 538 | 539 | /** \brief default destructor. 540 | */ 541 | ~dag_t() = default; 542 | 543 | /** \brief explicitly deleted default constructor. 544 | */ 545 | dag_t() = delete; 546 | 547 | /** \brief generate a DAG for a given block_number. 548 | * 549 | * DAG's are cached in a singleton per epoch. If this DAG is already loaded in memory it will be returned quickly. 550 | * If this DAG is not yet loaded, this will take a long time. 551 | * \param block_number is the block number for which to generate a DAG. 552 | * \param callback (optional) may be used to monitor the progress of DAG generation. Return false to cancel, true to continue. 553 | */ 554 | dag_t(uint64_t const block_number, progress_callback_type = [](size_type, size_type, int){ return true; }); 555 | 556 | /** \brief load a DAG from a file. 557 | * 558 | * DAG's are cached in a singleton per epoch. If this DAG is already loaded in memory it will be returned quickly. 559 | * \param file_path is the path to the file the DAG should be loaded from. 560 | * \param callback (optional) may be used to monitor the progress of DAG loading. Return false to cancel, true to continue. 561 | */ 562 | dag_t(::std::string const & file_path, progress_callback_type = [](size_type, size_type, int){ return true; }); 563 | 564 | /** \brief Get the epoch number for which this DAG is valid. 565 | * 566 | * \returns uint64_t representing the epoch number (block_number / constants::EPOCH_LENGTH) 567 | */ 568 | uint64_t epoch() const; 569 | 570 | /** \brief Get the size of the DAG data in bytes. 571 | * 572 | * \returns size_type representing the size of the DAG data in bytes. 573 | */ 574 | size_type size() const; 575 | 576 | /** \brief Get the data the DAG contains. 577 | * 578 | * \returns data_type const & to the actual DAG data. 579 | */ 580 | data_type const & data() const; 581 | 582 | /** \brief Save the DAG to a file fur future loading. 583 | * 584 | * \param file_path is the path to the file the DAG should be saved to. 585 | * \param callback (optional) may be used to monitor the progress of DAG saving. Return false to cancel, true to continue. 586 | */ 587 | void save(::std::string const & file_path, progress_callback_type callback = [](size_type, size_type, int){ return true; }) const; 588 | 589 | /** \brief Get the cache for this DAG. 590 | * 591 | * \return cache_t of the cache for this DAG. 592 | */ 593 | cache_t get_cache() const; 594 | 595 | /** \brief Unload a DAG. 596 | * 597 | * To actually free a DAG from memory, call this function on a DAG. The DAG will then be released from the internal cache. 598 | * Once all references to the DAG for this epoch are destroyed, it will be freed. 599 | */ 600 | void unload() const; 601 | 602 | /** \brief Get the size of the DAG data in bytes. 603 | * 604 | * \param block_number is the block number for which DAG size to compute. 605 | * \return size_type representing the size of the DAG data in bytes. 606 | */ 607 | static size_type get_full_size(uint64_t const block_number) noexcept; 608 | 609 | /** \brief Determine whether the DAG for this epoch is already loaded 610 | * 611 | * \param epoch is the epoch number for which to determine if a DAG is already loaded. 612 | * \return bool true if we have this DAG epoch loaded, false otherwise. 613 | */ 614 | static bool is_loaded(uint64_t const epoch); 615 | 616 | /** \brief Get the epoch numbers for which we already have a DAG loaded. 617 | * 618 | * \return ::std::vector containing epoch numbers for DAGs that are already loaded. 619 | */ 620 | static ::std::vector get_loaded(); 621 | 622 | /** \brief dag_t private implementation. 623 | */ 624 | struct impl_t; 625 | 626 | /** \brief shared_ptr to impl allows default moving/copying of cache. Internally, only one dag_t::impl_t per epoch will exist. 627 | * 628 | * Since DAGs consume a large amount of memory, it is important that they are cached. 629 | */ 630 | ::std::shared_ptr impl; 631 | }; 632 | 633 | namespace full 634 | { 635 | /** \brief The full Egihash function to be used by full nodes and miners. 636 | * 637 | * \param dag A const reference to the DAG for the current epoch 638 | * \param input_data A pointer to the start of the data to be hashed 639 | * \param input_size The number of bytes of input data to hash 640 | * \throws hash_exception on error 641 | * \return result_t containing hashed data 642 | */ 643 | result_t hash(dag_t const & dag, void const * input_data, dag_t::size_type input_size); 644 | 645 | /** \brief The full Egihash function to be used by full nodes and miners. 646 | * 647 | * \param dag A const reference to the DAG for the current epoch. 648 | * \param start_ptr A pointer to the start of the data to be hashed 649 | * \param end_ptr A pointer to the end of the data to be hashed 650 | * \throws hash_exception on error 651 | * \return result_t containing hashed data 652 | */ 653 | template 654 | typename ::std::enable_if<::std::is_pointer::value, result_t>::type 655 | /*result_t*/ hash(dag_t const & dag, ptr_t const start_ptr, ptr_t const end_ptr) 656 | { 657 | return hash(dag, start_ptr, static_cast((end_ptr - start_ptr) * sizeof(start_ptr[0]))); 658 | } 659 | 660 | /** \brief The full Egihash function to be used by full nodes and miners. 661 | * 662 | * \param dag A const reference to the DAG for the current epoch 663 | * \param header_hash A h256_t (Keccak-256) hash of the truncated block header 664 | * \param nonce An unsigned 64-bit integer stored in little endian byte order 665 | * \throws hash_exception on error 666 | * \return result_t containing hashed data 667 | */ 668 | result_t hash(dag_t const & dag, h256_t const & header_hash, uint64_t const nonce); 669 | } 670 | 671 | namespace light 672 | { 673 | /** \brief The light Egihash function to be used by light wallets & light verification clients. 674 | * 675 | * \param cache A const reference to the cache for the current epoch 676 | * \param input_data A pointer to the start of the data to be hashed 677 | * \param input_size The number of bytes of input data to hash 678 | * \throws hash_exception on error 679 | * \return result_t containing hashed data 680 | */ 681 | result_t hash(cache_t const & cache, void const * input_data, cache_t::size_type input_size); 682 | 683 | /** \brief The light Egihash function to be used by light wallets & light verification clients. 684 | * 685 | * \param cache A const reference to the cache for the current epoch. 686 | * \param start_ptr A pointer to the start of the data to be hashed 687 | * \param end_ptr A pointer to the end of the data to be hashed 688 | * \throws hash_exception on error 689 | * \return result_t containing hashed data 690 | */ 691 | template 692 | typename ::std::enable_if<::std::is_pointer::value, result_t>::type 693 | /*result_t*/ hash(cache_t const & cache, ptr_t const start_ptr, ptr_t const end_ptr) 694 | { 695 | return hash(cache, start_ptr, static_cast((end_ptr - start_ptr) * sizeof(start_ptr[0]))); 696 | } 697 | 698 | /** \brief The light Egihash function to be used by light wallets & light verification clients. 699 | * 700 | * \param dag A const reference to the DAG for the current epoch 701 | * \param header_hash A h256_t (Keccak-256) hash of the truncated block header 702 | * \param nonce An unsigned 64-bit integer stored in little endian byte order 703 | * \throws hash_exception on error 704 | * \return result_t containing hashed data 705 | */ 706 | result_t hash(cache_t const & cache, h256_t const & header_hash, uint64_t const nonce); 707 | } 708 | } 709 | 710 | #endif // __cplusplus 711 | -------------------------------------------------------------------------------- /data/headerhash_test_vectors.csv: -------------------------------------------------------------------------------- 1 | 0,9fa68736cb13eb975356e1f9abd403219557b3b9ec5b3d483130c12ced9efd82,0,fbf6ec7e3b9d667583f260d7c6b1eaf46092438c5e67533d612e045e3b7a294a,57560655785659264cd68c6835c6e8faa5e7c134f4fe18ae869c22b37707b04f 2 | 0,fbf6ec7e3b9d667583f260d7c6b1eaf46092438c5e67533d612e045e3b7a294a,0,086155810ed9a5f9ddc66ef34c2bc28b08e716e047e7bd1fb60febd91d9b54a2,e9ea5ad7324553b371f15cec467c13b51c90c19bb14d8b01078b3278898815ab 3 | 0,086155810ed9a5f9ddc66ef34c2bc28b08e716e047e7bd1fb60febd91d9b54a2,1,19173fcf34970d3efa6e3168956ef375015032a17f45d615a9c303b0aeeb64db,3eeaf798cf3d9d96ca69ddab313460474966d7aad7ba86922818ffd036b3102e 4 | 0,19173fcf34970d3efa6e3168956ef375015032a17f45d615a9c303b0aeeb64db,2,2db88378e5905d483fec0b9253ad5d26a04fbb272d7caf9da0d1c10d80c13071,6d50130be5f8a44079bf0d2f9e5b167813517a1e8602f5ff232cf9bfe3faad9a 5 | 0,2db88378e5905d483fec0b9253ad5d26a04fbb272d7caf9da0d1c10d80c13071,3,5d26a51783b8d4764db4b51f81b48ae3d33d7641d51154fdb8548df85882fe9a,6bf0cf8f6537959020f53c5c2c27beb05d68841697a932d847f3929979c1a116 6 | 0,5d26a51783b8d4764db4b51f81b48ae3d33d7641d51154fdb8548df85882fe9a,4,1d227cbda24eae5221daeeb888b08a3f527b4aecea5bfc21c094202a7d097618,e7f0fe3bc184d4360c8f8195204cd9c32ad21bfa08332bbd5e761f6e73e343ce 7 | 0,1d227cbda24eae5221daeeb888b08a3f527b4aecea5bfc21c094202a7d097618,5,42da09d439fc0852aef4d63d57cfadb68cf599224c319f3e8a2d1a933dd38c0c,6dee92ef2753a6f33e3c68a079813c60aa5f0664a41857362e27b25c64454cf5 8 | 0,42da09d439fc0852aef4d63d57cfadb68cf599224c319f3e8a2d1a933dd38c0c,6,187f182c387a316c2af61717b0d323e7a252436df82265d1b60ef644002ecfca,a1a6f2b7621df13b5f6d1cbcd59559e0672dba2a3160aef41aa0c20b31a9b999 9 | 0,187f182c387a316c2af61717b0d323e7a252436df82265d1b60ef644002ecfca,7,9323b862031c16b9dbc070b257b19f8846f217edcff998c755cfee78fb8d5667,781343a0887bd4ca0f5c3b7c231cab3cc74ec9e8cac3f5ed27185a94857c48af 10 | 0,9323b862031c16b9dbc070b257b19f8846f217edcff998c755cfee78fb8d5667,8,f06e32ab52fac865e3283a8ff0697dfabfae5b590d7aab80186499612deba719,f5d83d704b278773eeb30798efdf43407ae7113a8dadbcefdf2a56dfc81f788e 11 | 0,f06e32ab52fac865e3283a8ff0697dfabfae5b590d7aab80186499612deba719,9,bd2d5f3afc45d42152c27d4a179730d9a069cafa310bf1d03c42077833f1870b,f1a383c81670e91af62ec8285150c7ef04fd373b46fb18db8a0be5300846c9d1 12 | 0,bd2d5f3afc45d42152c27d4a179730d9a069cafa310bf1d03c42077833f1870b,10,dc7200e8b20b6d236f38a67ad0a5538f092699e333ff8c23ca316594e72b9bb2,ea60e5c749e0c0d93f9429874b8bda5f590fda296ee7a3edcc60edf3c2ae38b4 13 | 0,dc7200e8b20b6d236f38a67ad0a5538f092699e333ff8c23ca316594e72b9bb2,11,beda525fb4f3f29e2871ce2141ec1ad87b9c8f7e7354051526c98230c6b9a0d8,3261ae7a19bece2ab1b6d99e679be826dfd1e32eb648a1a9d1a4f1a27ef570ff 14 | 0,beda525fb4f3f29e2871ce2141ec1ad87b9c8f7e7354051526c98230c6b9a0d8,12,241c5d466e3652415a0ef3b23207680adf1ffc077a4ee1ce9890eccaaddfa499,b18376597c969f7ed618216ee4a377a275bcf7fac67b80c8ac32c9196dfe12a8 15 | 0,241c5d466e3652415a0ef3b23207680adf1ffc077a4ee1ce9890eccaaddfa499,13,32dc589a63ebaa2122a2b2dc8736ed8db330ad3b3b78627ad740589d26ab81f7,c5ffc2742962cb652e56072f7f6a843ca83917cfa76287f31f27ead385219233 16 | 0,32dc589a63ebaa2122a2b2dc8736ed8db330ad3b3b78627ad740589d26ab81f7,14,8f72cb92fe182c3ac298bc44b3bbc78905f76f7b3451c474b3078001f6f50033,79c371130db4ba3fb94fb4a87b856f4b2a6e859decef7a16a3f8828a66383ef3 17 | 0,8f72cb92fe182c3ac298bc44b3bbc78905f76f7b3451c474b3078001f6f50033,15,c62ca4935d1d085c016c1cab3ccb7c2212ce43869fb5bd60cc0329d56759542e,90e23fe22b6d28f3facf617b252cb2d45fc612877e8778e4b1623e4049055dcc 18 | 0,c62ca4935d1d085c016c1cab3ccb7c2212ce43869fb5bd60cc0329d56759542e,16,c46e3059e8c1147dc3cdefd4cf5bc30dc38176e18dfd08722a8246c5c1bb9036,62e8b2c0c1c3005dc7ab148c2d18adac4769541d61646c9d75b1df11f487b993 19 | 0,c46e3059e8c1147dc3cdefd4cf5bc30dc38176e18dfd08722a8246c5c1bb9036,17,b8163e74cd89e1311cf0121fe6c1fbce6c9554836f405a04b208344b0d4447cf,a7d16b768023b64b68f7634c9caa7be3a163228fd74d147d017ce5746953701d 20 | 0,b8163e74cd89e1311cf0121fe6c1fbce6c9554836f405a04b208344b0d4447cf,18,7778131f14f3c8a02d802d34e8f1117270c39d6350e68dc37719f8f3214c2509,74660f2d6169f1b116a561a5e058328537aa1605b4d5932816f286a05d10342f 21 | 0,7778131f14f3c8a02d802d34e8f1117270c39d6350e68dc37719f8f3214c2509,19,45395428127fea02d67c97fd25df5a59b27a0f4d9eb522eaf402d97c6388e366,bd35094bb3558b6e75ae954c55a500ec2b940c712663e3b5a6cc84758c910d0e 22 | 0,45395428127fea02d67c97fd25df5a59b27a0f4d9eb522eaf402d97c6388e366,20,dc56b304314bf4529163f29d1502e9fc81335adcb7631a2bb4c0906d439571de,e1984b6c0b58b2b01306ca961dfdc7d7a71f3bd0eb969f31305e42dc7217c556 23 | 0,dc56b304314bf4529163f29d1502e9fc81335adcb7631a2bb4c0906d439571de,21,1783f6193007d4557ab882800e4c03d7e653e9194bdc5097bb29b4dd79da4ceb,1dc7906072c5bc48a6ff34f2b7deda468766676610234e8c99d39d6a9aff96eb 24 | 0,1783f6193007d4557ab882800e4c03d7e653e9194bdc5097bb29b4dd79da4ceb,22,81d160660fc05a2c6544bf6d55a4fd9e321505b85a0b22ed29978c7f54db5bee,7fe960e0a7f6ac3424faf8f676ca32ad530f64c2b76108eea8808edd4486dddc 25 | 0,81d160660fc05a2c6544bf6d55a4fd9e321505b85a0b22ed29978c7f54db5bee,23,5f6b8757c3923a8839ab4aae91c14184c51439d2ff902a883b6d8c1863b8c75e,c34f75649c4f176d5a158844bf4ff24c6fa89d6015f274d74e252f3d9ecc2663 26 | 0,5f6b8757c3923a8839ab4aae91c14184c51439d2ff902a883b6d8c1863b8c75e,24,1264878e5736d1ba0d4b73e413eee72c293d752223d09c7ae9c390bef789cd12,a1ede06a62645fd642d9f9f1ef17f96e275900c6115d0044ac1d0cac017a9b8a 27 | 0,1264878e5736d1ba0d4b73e413eee72c293d752223d09c7ae9c390bef789cd12,25,5b2695fbd7bb9af8e3b1e93fc6c0ea9cecff5706dbe3825c0363a02d3462a863,2f8d102cf23086184c6e0f849da23dca8f952af3a0e992c7aa477b0a8b9a9b70 28 | 0,5b2695fbd7bb9af8e3b1e93fc6c0ea9cecff5706dbe3825c0363a02d3462a863,26,012c6bb1cd4c538472712bc39d18bda47c472c960a46a6e023066c01c4d18091,6e67fb1a2eb7d1ddfbca6d04c3921fd8010de1a409e4edd60d634715bd193bff 29 | 0,012c6bb1cd4c538472712bc39d18bda47c472c960a46a6e023066c01c4d18091,27,040254ad5e61414145e7942deb4c845772672d9c077fe1fe7fddee814df268f7,93105945fcd60758737d73204703257a560d97065e6a3074dcd0a6e1951988f2 30 | 0,040254ad5e61414145e7942deb4c845772672d9c077fe1fe7fddee814df268f7,28,b92ea137909e94077e43d691d3dc79e72aad9801fcfed53a79f1f9b10c23e0a0,10072f9fcbd89cb8d72fe1cdfa93c8bb98c70ed2e6894793267cb3d4f8f4e4f8 31 | 0,b92ea137909e94077e43d691d3dc79e72aad9801fcfed53a79f1f9b10c23e0a0,29,010be62fb861a38df07ca5e93b6152da8f2cf3d3fc373ed72770ee911e4e432b,1712a051a85545100b0e857e95196a07c1de9221bd2f6fb71ea03f54ff8e97be 32 | 0,010be62fb861a38df07ca5e93b6152da8f2cf3d3fc373ed72770ee911e4e432b,30,84156d379dd9b7ec5bf14d637034d538c377770407439166e1b7ed0d18a29ad7,e02cba00263d6452baa7a55d5456380bef42f2c18fac575ee350062e98e4ac72 33 | 0,84156d379dd9b7ec5bf14d637034d538c377770407439166e1b7ed0d18a29ad7,31,67b14790474dc73b85c83cc55e4d47f6f453ee92c7ba6e320190a22e23ae6224,a7bb801b1db11890bd82219d96e28499a2174b11143a71d3393c1725e86acfd2 34 | 0,67b14790474dc73b85c83cc55e4d47f6f453ee92c7ba6e320190a22e23ae6224,32,4b98d2ec24027299c2927bcba2a60403269e21eb9852b7e985852dd335336ec6,bb5889948cb72b8c25bf560de8c460b5181cca4109a655535000079b5c04ccac 35 | 0,4b98d2ec24027299c2927bcba2a60403269e21eb9852b7e985852dd335336ec6,33,f8bf2b897a1e931eb17d3ca61a14e9a35682c22920892584559ff83eb08bd600,a23d271b478add6127e9ac50208b190861bda83dd6ee048efb7a4e304b57193e 36 | 0,f8bf2b897a1e931eb17d3ca61a14e9a35682c22920892584559ff83eb08bd600,34,ab773870489779294d123c0f1c8982bd996f7035a5eb4cf2747fb3344be77ab1,3d517c9e24a8e4a904759f6e5a47bab18b78a59d3f3a6a7b31206d732ed642fa 37 | 0,ab773870489779294d123c0f1c8982bd996f7035a5eb4cf2747fb3344be77ab1,35,bbf70ab22b3f76ff999dc678d2e9bb75311f20599bb461f618afac2c40d60049,12b1b94ca110fe53e37d4b0e6b6f1a339bf439e99c1206c55eb2e021e5d6f7dd 38 | 0,bbf70ab22b3f76ff999dc678d2e9bb75311f20599bb461f618afac2c40d60049,36,b544908a2ce6e0608c50c562c2835cc9b09f13435bc1177c29d80a81803070eb,d28bfb8bfa78dd3203fb3c6d9de711cfb681e759872cd6fe675bfa07f60a3230 39 | 0,b544908a2ce6e0608c50c562c2835cc9b09f13435bc1177c29d80a81803070eb,37,812e7bce83672eeb78742afcbb205d3b352a5dd91d638227ea1ebbef8d36eb15,7e5bd29bfa2231fa316aef1ab094fe400ea711982b7d7bea7cfcb393005ea209 40 | 0,812e7bce83672eeb78742afcbb205d3b352a5dd91d638227ea1ebbef8d36eb15,38,338930d04ad12a1b3e86875461ce07e7b0f2024111a1cf600c1ed915ebda1b50,55e9a54c4ff1d4516101b4e2f719d87687fcc9ae442f169bf57794508fdc510e 41 | 0,338930d04ad12a1b3e86875461ce07e7b0f2024111a1cf600c1ed915ebda1b50,39,53a1649a9a09da5a5ee2aad342d11b256822312b96fcaaa10bf7f91b1693d30a,dc411b5015fb3660c419cf533d30701700641933c74f0de3d90ee7a26b93213b 42 | 0,53a1649a9a09da5a5ee2aad342d11b256822312b96fcaaa10bf7f91b1693d30a,40,ef7d43754e106aad266b3f18e0624c425592a0e55b45a4f2417261a3fb29b2b0,e18c7da5cf92ecbdb606c872db4a3f9e844398dff96cd01a4031100ebd9d09f7 43 | 0,ef7d43754e106aad266b3f18e0624c425592a0e55b45a4f2417261a3fb29b2b0,41,62ff5249df0c492da60c4493874d83639bc299d53d3b09aee720138c1c052637,9f6e0b89c425a2577581f09dcfc21fe77946ca9a58ff179f6bb9c3371368cb1a 44 | 0,62ff5249df0c492da60c4493874d83639bc299d53d3b09aee720138c1c052637,42,29b657f45505c7d32a98e2bdba839dd7f628b5a8437dfd04cc096311c6151bfd,b77e975009b79d75085ab55a2f11d4f5a93846b34f70ef040e06e133e3cf68e3 45 | 0,29b657f45505c7d32a98e2bdba839dd7f628b5a8437dfd04cc096311c6151bfd,43,f88f39c7410ac0c80b4bcc09373a88c6505c119da996b5ceb509ff94a07e6f4b,3f28e06eb21fdcfbff8b461869da43e0de52670594b5d600150230d22fc21f54 46 | 0,f88f39c7410ac0c80b4bcc09373a88c6505c119da996b5ceb509ff94a07e6f4b,44,98aa53f36f8a4e413f97b1bbb2a274cacb1a1e0e9c6c6ae0c7ee35349b3daaeb,130e39b86d25777c488870a4e4ad800aad33eb16d5bac8851d85ba652398c57b 47 | 0,98aa53f36f8a4e413f97b1bbb2a274cacb1a1e0e9c6c6ae0c7ee35349b3daaeb,45,7732c196ff445999e3427c612c4c3f6f94d883f6feb1a119530dcfd20936105d,738956ec58b8676f1e4b44d2fa97e67225015f554dc9a66913a1d8c03e4e2091 48 | 0,7732c196ff445999e3427c612c4c3f6f94d883f6feb1a119530dcfd20936105d,46,773d2d564eaa7f14ef20d35404a52d5b032a17a309519df2787313914e39bd17,b0989fe168efd409fa5138a1990b854c1dc1326d9b31ada41dc7cd0ddb2487ec 49 | 0,773d2d564eaa7f14ef20d35404a52d5b032a17a309519df2787313914e39bd17,47,955c387462729d351b1277debc9291966e6d2fd36e2b98c5cbfaa32dac2ef3c8,82d7ca623658c59536db2cac9a7117e91985aa438588cd9fd698296c7f0cd169 50 | 0,955c387462729d351b1277debc9291966e6d2fd36e2b98c5cbfaa32dac2ef3c8,48,7d0d9b32fe3da11f0145ed1f8efe1eeace510a21fcd7143e3fda597c8df77f4c,8813bff19abbaa3e72a44a172c1ceda06c3f5ff9a3caab0b5b80b63ee686dc38 51 | 0,7d0d9b32fe3da11f0145ed1f8efe1eeace510a21fcd7143e3fda597c8df77f4c,49,11bf947839b9d7a71f14f5d2a746a1891acf01013f424b2c94bd37e1b8d1deed,674d6f86ad9fd470df28b125fe7cbc99ed14e9cb4a0571cf34332df52dff6b39 52 | 0,11bf947839b9d7a71f14f5d2a746a1891acf01013f424b2c94bd37e1b8d1deed,50,955f239473c76434fbe94111634741fafc5a933d2b85b55e70575845d6b95146,76297fe1cc16a08d9296ea1dc3906e981d135a1b1ec40dace63c5046ff2c7b09 53 | 0,955f239473c76434fbe94111634741fafc5a933d2b85b55e70575845d6b95146,51,7d6e93a0fa2f497e63ca21c6b50cf56d71fb75f6e67a016a99118bda8bdf13ac,5b910c2a5da37b730fe2ec6fed7da0e802614a28ad6ab8b3ff45dff46b950762 54 | 0,7d6e93a0fa2f497e63ca21c6b50cf56d71fb75f6e67a016a99118bda8bdf13ac,52,69921e7139c37673b7540d035b4ad4241591219c09b5a9c29f26f38f8f6fe0ec,d47bd50ed0e6d8dce1816ca409448e10a9e391cadf2b4bb1692a8a2965ac510e 55 | 0,69921e7139c37673b7540d035b4ad4241591219c09b5a9c29f26f38f8f6fe0ec,53,2200b70211252842305b3f2318d00eed96b89f80612e27fa8d5c6ba16a52f53f,a60562a93b59045ab05bb972b350712bdbf7a3d5a36928a5542dec9399aeecd4 56 | 0,2200b70211252842305b3f2318d00eed96b89f80612e27fa8d5c6ba16a52f53f,54,a51d6b624cbc6901d77d979da637fd0cac8a34057b6cd0ee4b763e341ac58a4b,8f625deb5c86109ba902d3cde77cbf5e745b229c9ce54fc9733b2dd2e225ed1e 57 | 0,a51d6b624cbc6901d77d979da637fd0cac8a34057b6cd0ee4b763e341ac58a4b,55,7fb464c18885e49a8ec053b2342b812ebcaca543699343782a40b042c11dad2b,4ecb9b85ccf3d09c29944351c18aedce0abcfbd56b6b1aed3ddfb3c97f176c97 58 | 0,7fb464c18885e49a8ec053b2342b812ebcaca543699343782a40b042c11dad2b,56,953620875126d7d5434b315b81263ba4ac3c99cd7e60664bb539a57b21ba3aea,909c756b996643a031d48e05e3fad6639cb7909e4a1364960146a05c551059ba 59 | 0,953620875126d7d5434b315b81263ba4ac3c99cd7e60664bb539a57b21ba3aea,57,53a8c3c2da67f0bfd56eb710c7bfab3e826d0f4aa71239402ffa5e86a6c5176f,ede5ef43f4b1ecc84cb8dda461d6b9cc35c1b47a39ee516f01ab2cd5ea63dacb 60 | 0,53a8c3c2da67f0bfd56eb710c7bfab3e826d0f4aa71239402ffa5e86a6c5176f,58,a21e5581036f473fcd5df9b4a7871226a67a689223c3c475f17fc494bff67683,d643c35451719847ab506feaccce9ede1c7bd33fec059466118b69f5381f21fb 61 | 0,a21e5581036f473fcd5df9b4a7871226a67a689223c3c475f17fc494bff67683,59,eacca37db163e345a53f537b70b73983c4df1b1faa45b50e53a6396387eb78d1,190ed2374fb3d6802e1dd4deda636b11c07d094ec1c22686514b5ee9e5598d6d 62 | 0,eacca37db163e345a53f537b70b73983c4df1b1faa45b50e53a6396387eb78d1,60,636c7637571b563fd81e97b9654e376886a1a147bf45217009f609ff1b7113f8,413193c3a3e417b03d9041f524146156d8548f596de8bb6a4cf0c26b75f1da6f 63 | 0,636c7637571b563fd81e97b9654e376886a1a147bf45217009f609ff1b7113f8,61,78491a7e644f482a8851e927e9d4087136ef422bbe01026ce3c8da8b95542a36,df6ebd621aaf9fb3bb299cf7bdd8b4e78dcc61f89b342228a4b6ccb07a916eea 64 | 0,78491a7e644f482a8851e927e9d4087136ef422bbe01026ce3c8da8b95542a36,62,4593305d56b9c84fd481f475c49af7edb8b2880dbc1788bd647dccd658ec84d8,f6f683ebebeff032162c00a90147c34046ff5a02d4a27b4bd4ecda759b68e1ae 65 | 0,4593305d56b9c84fd481f475c49af7edb8b2880dbc1788bd647dccd658ec84d8,63,1416aa43e54519663d2cbc92cae6459db8546b6bce5961fc14a15e3a425b1723,a2e22d6366beadd0b0e54b155a2623729c00d6c9765e5728baa5b6e084ed7507 66 | 0,1416aa43e54519663d2cbc92cae6459db8546b6bce5961fc14a15e3a425b1723,64,c1ac5c55b5fb2b0a94c913dd7c59c972828137026ca64b4adc27b64a2e051151,e0b7aa308bcab8dda2054865ab145d8d1de8aae201d9cde63a183b8913f385a9 67 | 0,c1ac5c55b5fb2b0a94c913dd7c59c972828137026ca64b4adc27b64a2e051151,65,2dbbd2e832e8f6446d6c7ba8f82c24d534d7a88fdd77e089d963208a212c43d9,7d02464362f28c4d56612b59c338c8e198880fbf26b3011241e59ad23cfc7e25 68 | 0,2dbbd2e832e8f6446d6c7ba8f82c24d534d7a88fdd77e089d963208a212c43d9,66,1cfbd21743ce6a25852adeaba72dcb05b28e5a3b47eb5183013d06fb366596bd,02bf11ce929426e56059b5736d29ae0f31aa9c3b04025d54e90509978c20594b 69 | 0,1cfbd21743ce6a25852adeaba72dcb05b28e5a3b47eb5183013d06fb366596bd,67,fa3ae22e3eb7869e9de7eddbcc8f254898257340201e7457a589d632aea3f389,6f2c74c9c4c09226b37b73be29baf34c6bcd02d135406428fb9815f9d3480cc1 70 | 0,fa3ae22e3eb7869e9de7eddbcc8f254898257340201e7457a589d632aea3f389,68,fc2f1d2d96a5f66e7be1d8bb3a1dc336541275f882a67933983b0d830a5b44c0,c9e7d7d57de90585cff2f9dd7dd8603b90bcf064bcd915d89d5beb431e8f0b61 71 | 0,fc2f1d2d96a5f66e7be1d8bb3a1dc336541275f882a67933983b0d830a5b44c0,69,9af76e5afda7ed8ff616c48317a07d13e5652eee36095ffde172eab5bed8ece6,602ebc235c93f205ec11b3bc3dd012d44aea70ed7553daff4905972e462a86b0 72 | 0,9af76e5afda7ed8ff616c48317a07d13e5652eee36095ffde172eab5bed8ece6,70,ba849d712e81299e69f3d2e7315468d19f6d3d579fe6e3b793ccb490712f9fd4,4a8d46d1689b467acc7f8d52cc00bd9a769d92b3e8dda86ff9da27a3079bf5b7 73 | 0,ba849d712e81299e69f3d2e7315468d19f6d3d579fe6e3b793ccb490712f9fd4,71,c0a89f7584b2a732ef109b7d37d45d0a30a16cc4129f662f1f477f2aa992f097,6ee847654e730a6b8d43c221a4be40fde2a99055dedd738836f935aa54f1c650 74 | 0,c0a89f7584b2a732ef109b7d37d45d0a30a16cc4129f662f1f477f2aa992f097,72,0229b52d100ca926d333e4ff0b145fd1ef84b3eed8d3556927c692acd2cf5638,2518e6ddea1b389101175eee92c0be35040d13aebd3d33cc420f5b26b41ede0f 75 | 0,0229b52d100ca926d333e4ff0b145fd1ef84b3eed8d3556927c692acd2cf5638,73,3e28303e0ac61d83ad72f497879cf2176dc12026a051884041d0e03658a50120,30edd89351440fae30c503407c151eb61966cd6ab8a4b546399385335e786075 76 | 0,3e28303e0ac61d83ad72f497879cf2176dc12026a051884041d0e03658a50120,74,ffb3e014e68b60454668ffea85e9e9dce718e9e94a4b8004acd56b70c21b4cd0,cd222a69aeeff52f48711fe8d054223556b6002fec139520aedeac2d60a6e8f2 77 | 0,ffb3e014e68b60454668ffea85e9e9dce718e9e94a4b8004acd56b70c21b4cd0,75,42d71db4629740c0c6b4c60e84e991f9b9b56a57b9a8e30b197f3de050a918e3,0da4104b6703e7e697c2c42c18a45acf97d7c75f6174563f6747bcef80b186ae 78 | 0,42d71db4629740c0c6b4c60e84e991f9b9b56a57b9a8e30b197f3de050a918e3,76,95c4bcb18087cbbb125a84aa60317e1c1a08114ba3e25b462e5e4978e4dc10aa,f5933e939bdabc1baa72f1d15ffa3b0138b57de48586b827390a08af9d2490de 79 | 0,95c4bcb18087cbbb125a84aa60317e1c1a08114ba3e25b462e5e4978e4dc10aa,77,44fedcbc5ca317027a59291cb63c418dadbaceac3e0e0cdff5255a76aaf57b56,fe691ac4841b99f425db306c96d33a55b9b75ec67ebfed420de118d58189a75b 80 | 0,44fedcbc5ca317027a59291cb63c418dadbaceac3e0e0cdff5255a76aaf57b56,78,9c19abd2b1715b3cc185655e70e8e6fd5dfab8f1c0fc6f8f530d73e0324b7c26,5bd10c1f03dc055caac1d63f1780115475adcc3983a9ddcb32b77062a1845b53 81 | 0,9c19abd2b1715b3cc185655e70e8e6fd5dfab8f1c0fc6f8f530d73e0324b7c26,79,56385270b1eb76d341940862342cf12bf261171429283d57ce6d05be6eb02a84,1268c594874c0116088cba955a4babb6352ae81868728f8c0351460679db8ef6 82 | 0,56385270b1eb76d341940862342cf12bf261171429283d57ce6d05be6eb02a84,80,35f2c729cf038140e2640ccea5a59bcfcb17f139c730d865043e8a6960205872,80f55f7b6fb9e74d5da0bfcbe5ba3f9138a65877e25827e88e980567fb1fe34e 83 | 0,35f2c729cf038140e2640ccea5a59bcfcb17f139c730d865043e8a6960205872,81,97fff61efe63df9e1b0421c56c87223b392dc1a66fe9164f728adb2b94cbba7c,55851f02fd48e2313deaeac0282962e77292f1ac0a44ac927690f42397e0cde9 84 | 0,97fff61efe63df9e1b0421c56c87223b392dc1a66fe9164f728adb2b94cbba7c,82,cd01f286c0d1f31eacddd7ad100fd05dbab250f0793c4a52a9fce82304b235c0,d2fe2f2f880ebd181b2e201ee66cbc472b67009218c9eb83d0861bb379728484 85 | 0,cd01f286c0d1f31eacddd7ad100fd05dbab250f0793c4a52a9fce82304b235c0,83,33d51621d55561cc8c890c4b25aff51f0b22edf4a9f11bd7ca2bf09f362b476e,adcba530eca51daf6fdbf6649cee9970b5b238611d4d9fb72e3afe8f50f0097b 86 | 0,33d51621d55561cc8c890c4b25aff51f0b22edf4a9f11bd7ca2bf09f362b476e,84,84780fe9190d4123cebe845b3b033283b37c43673f809e9ffe57cc1e7ca09b20,b9831e779c76fd091132258dd252043496bf248d21ff06b0534b7932caadc636 87 | 0,84780fe9190d4123cebe845b3b033283b37c43673f809e9ffe57cc1e7ca09b20,85,3d095b4d5ff056c038054db7eaf1741c4df513b162bc5b082ce366a92e1c10cc,d9c449dbffcd525ed48633094dabaa7197cc6629f50759c971b3e9cb8bc8aeb9 88 | 0,3d095b4d5ff056c038054db7eaf1741c4df513b162bc5b082ce366a92e1c10cc,86,d2d60d7d8a3b70d25babfc8ca51af4582205e9ee1b2729f8220478d8d4ef8f5c,b2c0021ae2cc6cb4dcbcef762d6ab6f91f77a75d9c709752e8925ba3f1ddd9e2 89 | 0,d2d60d7d8a3b70d25babfc8ca51af4582205e9ee1b2729f8220478d8d4ef8f5c,87,53f0e21e6629c0bac9e898c6322918d09f695ca8f5f8d210fbd174fa0e91f348,aaa8e6394b3d013d1fc1a232dea2b2af76093bf93cb7431cf73ca06680ba3f7b 90 | 0,53f0e21e6629c0bac9e898c6322918d09f695ca8f5f8d210fbd174fa0e91f348,88,697a4fae7b4c4180a14e403781ccd8661582c081ba158c982e3acbd29db80abb,1ad4bcc2319af5ee757410183ce274e6647d9e347d4ebab73ee931b66028e98c 91 | 0,697a4fae7b4c4180a14e403781ccd8661582c081ba158c982e3acbd29db80abb,89,f5646c833c5f7e40e0f91eff9063eac49add5aed0d110159d7d878772d234e99,58703af4918f8778d33a23fafaddbb6eb9e04eca4f6195749e19561c2db40337 92 | 0,f5646c833c5f7e40e0f91eff9063eac49add5aed0d110159d7d878772d234e99,90,dc9b884838c1953f2226819097e7f5d98007d78d94f9d46157beea53468d506a,0ed7e3261c3e31559dc9e164016b1b87733c404427c47feb70ca61d7a7e558a5 93 | 0,dc9b884838c1953f2226819097e7f5d98007d78d94f9d46157beea53468d506a,91,46c8a4ca94edb9ed0edd6a421f2b17d8c2669bb9fa999f566f6a4405fe1f6182,78eec45c3a90fcb1c9944b775914a14f67272ea7bf7666ba1e4570b9d314eec6 94 | 0,46c8a4ca94edb9ed0edd6a421f2b17d8c2669bb9fa999f566f6a4405fe1f6182,92,afa8b301c7b2e471063eaaaaed299cd0507f5ae2298497f8a217523a1b5da2fd,db5f8e24d40cf33cf466a1cf393083d2a9c5873f3f8bbdbb36bb89df3a581108 95 | 0,afa8b301c7b2e471063eaaaaed299cd0507f5ae2298497f8a217523a1b5da2fd,93,44f6a41af92bc4456b82c9d35ab169801b1c76422c859751389ca161d925a47c,5a78af25631e283556ed5c5a0c3f317352ef2dc0f1a9e4f93b8e332907730fd3 96 | 0,44f6a41af92bc4456b82c9d35ab169801b1c76422c859751389ca161d925a47c,94,82da15b2ba950969d7f8a865aedcb4b209930fd32b6fe900f75cc6581d796378,37660c755c8b5c87b3186f661e9bd17edd1ff63e3bb5ea8a0812558b2bd03275 97 | 0,82da15b2ba950969d7f8a865aedcb4b209930fd32b6fe900f75cc6581d796378,95,2b38019fa01466082add52121bbe07af8576d713f24aa4de7e5a9abf9bba776e,8b740fe991677c7e7bd283b798a0a641cfa1384a3edd1800f736f287515e04fb 98 | 0,2b38019fa01466082add52121bbe07af8576d713f24aa4de7e5a9abf9bba776e,96,45ce00c286162ffbc1f791520777fdc583510e9e19c395ffd049ced3787cc08d,524ecd05719c4597e3f6f9fbfbc851bb1ba4a7cb60526e340dc31099c3fa4a79 99 | 0,45ce00c286162ffbc1f791520777fdc583510e9e19c395ffd049ced3787cc08d,97,df98c4c536bc372b46d21662624ca578b51252ce72737898f8d7c08c73ef067a,fd91f7c7ef5f6e24ca000e97e9f3de80cddc81034561e43279daeb4a0858fb35 100 | 0,df98c4c536bc372b46d21662624ca578b51252ce72737898f8d7c08c73ef067a,98,76cbb345bc399992255d9ffd0066b2ac913d7248ed82d20dfcf437b29f58752f,398249817891996299dce12ee0df7dbc123bd3a5de5c16c58e8aa00a22dbc00f 101 | 0,76cbb345bc399992255d9ffd0066b2ac913d7248ed82d20dfcf437b29f58752f,99,ac5bab88b8960f84660bc467d821f61da232f863239bf789c2676787be0d7bb0,181f47071030bfc3aa02b9461ce0aa707161cc6cd24fab55cafd4c08a028bd78 102 | 1,ac5bab88b8960f84660bc467d821f61da232f863239bf789c2676787be0d7bb0,0,8c8e60355da2fa21acfa8ad0d5fd920ac32925cde39883cc3f158e85fdc92153,50b9c3f36b3e6c0d963eb53352456ccca41dfbe5f2b0ad35a81c5ff6caa7c907 103 | 1,8c8e60355da2fa21acfa8ad0d5fd920ac32925cde39883cc3f158e85fdc92153,1,7d11f057dde63aa52e7309ce7a1a72c40f2feb30565028cee6dfaa51e21b3f88,83143f334beeb4dd4ccd4c40de1255523c4d48ea302046e6de4677e86d345cf5 104 | 1,7d11f057dde63aa52e7309ce7a1a72c40f2feb30565028cee6dfaa51e21b3f88,2,0ad80b95598d0310a54331b46cb10b51aa78aae1289906c58479744e46e0f746,3ef4532110c1078564a08b79f7c8f430c9f61b2f3bffbcc0f9c30ca2f415d050 105 | 1,0ad80b95598d0310a54331b46cb10b51aa78aae1289906c58479744e46e0f746,3,d28220f0a3f108d08cf607c08b381e0a05fe39f59c2a7b0b449dd56b9903580c,6ae3fa8ddb5a6985c39755dbcab5b71119ca4efbdb23c45bac396219416c3aee 106 | 1,d28220f0a3f108d08cf607c08b381e0a05fe39f59c2a7b0b449dd56b9903580c,4,b746eb67044e78863bad859ce2d742a0410a4186c0a0ab57a4fd202a07fe59dc,4fb3bba3f0f2185d4f0fdf5a45280507969e73ace4b15068c7c47d39b51079fa 107 | 1,b746eb67044e78863bad859ce2d742a0410a4186c0a0ab57a4fd202a07fe59dc,5,12675fa34cecdc20338ac7a8c10530c87ede0b3a80689ee8c5ff65a0b540e320,b81ff51e1da83ac283af8851c16b9572290715fb96bdc090bc88cbe20c30267c 108 | 1,12675fa34cecdc20338ac7a8c10530c87ede0b3a80689ee8c5ff65a0b540e320,6,39ecfcc71c7a2c0bd497fd05d48ea5accfca7e85e93533ed326e92540f756e2d,8342e18581ea272b1f32d3c51d339b8343bdda4ad557fd88a17ad92b612d5dc6 109 | 1,39ecfcc71c7a2c0bd497fd05d48ea5accfca7e85e93533ed326e92540f756e2d,7,211a0d87e75aa673cd399557c7ec6a3ace53d0a4540aa4e441c9f3555aaedc8b,676451644adfe67d7d967c79afab9206841f43fdc8cc2acb01ea914611b3fd07 110 | 1,211a0d87e75aa673cd399557c7ec6a3ace53d0a4540aa4e441c9f3555aaedc8b,8,c2e99bd4d999b969000a674a9adc3185eed3b48c3de8cf03f4b997806de819a4,d4a26f58ed1dc0256a0403bc21372009e7f73ac4dc1908b3700dbf37fff86671 111 | 1,c2e99bd4d999b969000a674a9adc3185eed3b48c3de8cf03f4b997806de819a4,9,6948264177d6cc531bf2faf560a59b3aba784a0ce6729b2c997d6e66dac424ec,5d074a97ff01e34e58693a9870d44bacf58d2f7d237d21515f60c97184875309 112 | 1,6948264177d6cc531bf2faf560a59b3aba784a0ce6729b2c997d6e66dac424ec,10,1c7196c8dde8e7cff67c0cd4643deb74867aa2f91630a4d2c7f611f04db30da8,e6ec1d714619b01a3b0e1d54adee2631a471de115b27a90cc9db3088cfe0305e 113 | 1,1c7196c8dde8e7cff67c0cd4643deb74867aa2f91630a4d2c7f611f04db30da8,11,7a1bb0a223a304341876b368aed0e3d1dc2658866209bd17defd8a7935ebc2ea,bf5bfafd9fcc05dbc77666933231a8b39b51b5d30d402b603d774fa11f0b2277 114 | 1,7a1bb0a223a304341876b368aed0e3d1dc2658866209bd17defd8a7935ebc2ea,12,d9ef28e47e309f54387b726c0829378e5e34f3bb1ce420d8118e0b90ecbfaf25,219e3faccd35f3eed71a9e72e61a58276edbb83f0e9dd9b1256c597e5f5a2e93 115 | 1,d9ef28e47e309f54387b726c0829378e5e34f3bb1ce420d8118e0b90ecbfaf25,13,28d162539e14eabd136422da5d320a0658ada942a7227709a7348280541ddb37,3c06d0c7eb6cebef3993c964b679746948c1f735b93a20e43571c5636aa1e6fc 116 | 1,28d162539e14eabd136422da5d320a0658ada942a7227709a7348280541ddb37,14,4cf016bea1fa13a24c97486415586d4242d445649494a9f77e5e06dc97a4dfd4,b019a71b9f29dc3eca48ded93ce40e061d2d5dbbd09fe13eccf8ef4d3b6fb265 117 | 1,4cf016bea1fa13a24c97486415586d4242d445649494a9f77e5e06dc97a4dfd4,15,06b5d306ebc2115107827483994cdf021561068bb1200d6fcb0e6086d91d045b,db3f4df9deca806d7a344ad0c1a2bcefa7813ebe5cb975f160e16852d4bbd060 118 | 1,06b5d306ebc2115107827483994cdf021561068bb1200d6fcb0e6086d91d045b,16,5aa3655e0188bf7d1e6627e83bff71ef58489b338c513a9deee2a1c270482179,785b59e6b54b25530a18a8be0c7ebed087e8cc148c23d2ad0d5fbbd3921fc2fd 119 | 1,5aa3655e0188bf7d1e6627e83bff71ef58489b338c513a9deee2a1c270482179,17,41e9aa43d147e24ebb350c7bbab6857e0c81740478018a67f4372fb531d2b53f,78cfb47dd1863d80bc87e62f3a4dce714a647d7a163141c1e0ba2be9cecfe88c 120 | 1,41e9aa43d147e24ebb350c7bbab6857e0c81740478018a67f4372fb531d2b53f,18,596454692415649991250a93b48f1425199bd5431adde16b79f3f77adb05e80b,f9514793814c1f44b4e28f75eb32fee404543499c05e0ae423f6c62f307a7ce7 121 | 1,596454692415649991250a93b48f1425199bd5431adde16b79f3f77adb05e80b,19,290ec0c967a38a4c858c0828eb40c73d42b7b6c2bfa3e78760aa98796ef9848f,59c71ed3e50e2e8e18d4f78484038f5e2b18cddcfca4a361182c5a7205de6f32 122 | 1,290ec0c967a38a4c858c0828eb40c73d42b7b6c2bfa3e78760aa98796ef9848f,20,97f052f9e62f2c919047bd4e1e46b3609249293a1bf2e9e0924b69430b967bc7,b7e6bc2601701ceee836fd2a51ed228d2b0bac7277d4d02bb6c343c0f8992edd 123 | 1,97f052f9e62f2c919047bd4e1e46b3609249293a1bf2e9e0924b69430b967bc7,21,ea430de0234b5b0e6af69e8281619068b6fa5191896d51ac2b4371d3f9e9ba04,4df660f0003b9c23e965ceb911b56809fe7da3ed252e293b581927e85fe7931b 124 | 1,ea430de0234b5b0e6af69e8281619068b6fa5191896d51ac2b4371d3f9e9ba04,22,87219634d0fc106f2aa66a7d1ed8e86e53c8c79ee8771372e4c82237f9e5e352,86bc0b07bc1746e40219f14433b6eb22dd2644cb105ad67965429e1c80e21e73 125 | 1,87219634d0fc106f2aa66a7d1ed8e86e53c8c79ee8771372e4c82237f9e5e352,23,d15ed7e76c5d6518720b14785c081c6efbef30332eb3ada7cee10a1e1e68443b,1dd5794f6e09fee8709b0c3d7cab6cb10756a4dcd63fa6ee2158bd7e2c9c50d8 126 | 1,d15ed7e76c5d6518720b14785c081c6efbef30332eb3ada7cee10a1e1e68443b,24,ad457ec5a7f7afa61a81bc8f9ba08ef1c19496d846ec4d6c6da65c1f028577cf,1c3fc44366d7c5ce8b1398875cc103c2be06619ea385fb659c0f6f080a0689de 127 | 1,ad457ec5a7f7afa61a81bc8f9ba08ef1c19496d846ec4d6c6da65c1f028577cf,25,3980b02f4c341e65e783a9fdd95894530880182c94e3670a93a4da09bc6a02c6,f3e7ee76fca6880ad70a692abcbf733730c12331f36866310bae7071886f23d2 128 | 1,3980b02f4c341e65e783a9fdd95894530880182c94e3670a93a4da09bc6a02c6,26,64c95de8f34a054fafb6ba6baa606ccfa70f209e6d238d2da387a61107abbd8e,3b0141f704c1ce50ad6eb98689341f5cdf0fc12800dbe17e2eaa5d7bac6b3abf 129 | 1,64c95de8f34a054fafb6ba6baa606ccfa70f209e6d238d2da387a61107abbd8e,27,f6be082ef416a996e3e7d2f406950bb86d1211e80e754f1cb06ce40693fef2f3,8bc2abbc191db0896d83640fcefec6fddbe803e24666d6063680b1a6d5ea6033 130 | 1,f6be082ef416a996e3e7d2f406950bb86d1211e80e754f1cb06ce40693fef2f3,28,e45d8b491553d1966b9b3731c32ceca5ff4025608b6752c8efd359e7eb85182e,c44bb5a18b47669cb3b4c58f18b70564dfd10926334506cb0d3697b9e911ad05 131 | 1,e45d8b491553d1966b9b3731c32ceca5ff4025608b6752c8efd359e7eb85182e,29,26525e6dba39cc4a42717e9fa7c52e015a110ee27664f717183bb18caba09157,ebb9e31c1fb4fc42b939eec974bfbea9479e9d2c82ee2acb665df114dcfa7e91 132 | 1,26525e6dba39cc4a42717e9fa7c52e015a110ee27664f717183bb18caba09157,30,3296a0725b0e0c5fbc6f9325e133f189e098cf196b0d304cbb617567aefd9cdb,922be25454ded0525ad15e22a42cb9b94a8bec8bbb7e7eb8ce945bd11b0f8c6a 133 | 1,3296a0725b0e0c5fbc6f9325e133f189e098cf196b0d304cbb617567aefd9cdb,31,eb8281e86f16d05d967f498f07c5d1d6e0d7f01cd34faec9f9e80f3ee0a74e50,9ea774ce76fd353b87cba26bce2eed634f599b8eb9b827f02f50165225daa1d2 134 | 1,eb8281e86f16d05d967f498f07c5d1d6e0d7f01cd34faec9f9e80f3ee0a74e50,32,a2fa3fda8ce50dbe2bdbe4acdc1d4c6bba8140fcec7e44b03084e889240ad238,d50af92bab7ebf63473f50b7e4119956104dfa7a2786c1785d3fe6ea81af90e8 135 | 1,a2fa3fda8ce50dbe2bdbe4acdc1d4c6bba8140fcec7e44b03084e889240ad238,33,2274fb20c4c7393919ed87e323db902f87ccba50a0d18c33b7b7a5097fbd9015,00e9354f2301fd052f67d1c8f2c1f264f8093934098b6ecbfa6ffa472ecdc810 136 | 1,2274fb20c4c7393919ed87e323db902f87ccba50a0d18c33b7b7a5097fbd9015,34,7369baa35dcbfe2a844427bf58599ab42d151219360ab19b7ceccdded979e81a,6ba5644439c335fcf8bc813f12945252653e35286dd177aaf84a0e2d5e54a4f8 137 | 1,7369baa35dcbfe2a844427bf58599ab42d151219360ab19b7ceccdded979e81a,35,af571a4ff87fe6669f933ec33fdacabfb49ace0e0bc3e20311a6cee68402107a,e2b455cd6ff42641a379c4c7295a3ecf249a024f01eec295b9868b8ff2ba0d5e 138 | 1,af571a4ff87fe6669f933ec33fdacabfb49ace0e0bc3e20311a6cee68402107a,36,ec1bb5d537adfa3be57e763dbcce5dedee4907d09d4839b73d95d9d8a41fd348,448a693a25229f0fd84284372bbbcea1bbbdb2f374b76dd0dda88824ef4107b8 139 | 1,ec1bb5d537adfa3be57e763dbcce5dedee4907d09d4839b73d95d9d8a41fd348,37,8cc1538cbec1b54e11a0ef389b97f7a340ec2feb650221ff0ebb9d0edcfa910d,d96d710ad15004ef7ac5c160bc16afa37e6a9adbc5c3aa5ed281a50992695b66 140 | 1,8cc1538cbec1b54e11a0ef389b97f7a340ec2feb650221ff0ebb9d0edcfa910d,38,c996f1d540ece2f05754c0de2a032bbf8f8039cb9388576cafcb56389aaeb620,78d72f90089b7352492cb53d179d3a198e0b013f94e3d908a4a070314788b7dc 141 | 1,c996f1d540ece2f05754c0de2a032bbf8f8039cb9388576cafcb56389aaeb620,39,605a55aae91b243d00158aee37014524f54f66022bc6bfc4794948a3113b1d5e,49ce880d51bec8352a7cf362c4c9ff613bd0d701c026643c206f894db665684a 142 | 1,605a55aae91b243d00158aee37014524f54f66022bc6bfc4794948a3113b1d5e,40,0dbb9cc0d921ec62b17879a037b1c6aa76128b85986299f411f45329e4073ad3,b024792df3f07ce23b7bf6fd7621ce1baef407e15df0feb04bfdd9b888936a52 143 | 1,0dbb9cc0d921ec62b17879a037b1c6aa76128b85986299f411f45329e4073ad3,41,155c68736cdbd0c8096b8ce6ee5a51986f908b0a41b92134cf45fb5033c39975,c454449c51f70e63cf7e884b2072cf1be90d1682be6fc9ba392ce5e82f9544c9 144 | 1,155c68736cdbd0c8096b8ce6ee5a51986f908b0a41b92134cf45fb5033c39975,42,16e246c33d60c9ed0b5e306b8f11139ef8a6270279328f370b395969bb6c7458,064d1bf9441eeba7e43d3a7e86bb0fb574c6df7b91351501c44cc82ac9ec4b2c 145 | 1,16e246c33d60c9ed0b5e306b8f11139ef8a6270279328f370b395969bb6c7458,43,bc0035343c70c5b7ea3fa912f92568a578fba0dc5f9efa3f5a030385c7650ea9,22d956f7bd43e25b513f39a793689a81ace01b849dcc29144ad75543ac032c45 146 | 1,bc0035343c70c5b7ea3fa912f92568a578fba0dc5f9efa3f5a030385c7650ea9,44,ac96c7454d3b8541103c718591b9116c508a91687c384bfcbe15ada17b0df22b,e26c468baacf5cf4d0169f82362b0623653ef9830e9fb2f5e00bbdadfd45882c 147 | 1,ac96c7454d3b8541103c718591b9116c508a91687c384bfcbe15ada17b0df22b,45,f44bcc7ef8a911a0061090af08156861a03c76f2ed4ba1249a963b4de55cc73a,aa74a1fcea5811e587516cf81877a256a7dac810d9ce9978a84b7902c99c7e19 148 | 1,f44bcc7ef8a911a0061090af08156861a03c76f2ed4ba1249a963b4de55cc73a,46,2723edb8956c2431950e8ba8a5b557a7de43c856528b85ea7903f640bdae7e40,f5698a42b114ea07a2f141f68a7677d623cb1365e899b2407fa676fa74267733 149 | 1,2723edb8956c2431950e8ba8a5b557a7de43c856528b85ea7903f640bdae7e40,47,af23a624ed5d6bf561838ba97c08d61a7d979517632176162502f22169c69c2c,f5a27d5185ecc3d5bf1f98bda9cb52b0539a6e5669431f4f75fcf7e16c80f302 150 | 1,af23a624ed5d6bf561838ba97c08d61a7d979517632176162502f22169c69c2c,48,0ce1eddf3662c1a76ca72198f597664c0bf5b13d98c23a47b5cf99c60c1ec533,d59366a5697127c24b4ca828e7c9f79cb9b142730143bc56dc17a2fb67d82d1c 151 | 1,0ce1eddf3662c1a76ca72198f597664c0bf5b13d98c23a47b5cf99c60c1ec533,49,07971aef1b977295fecc687397c0e788d474d1e772d09cf614a87e7065fbb967,521a251e3b03705cb98ff69630c015de2b90cac99a17a65fb1d968c5599a6af5 152 | 1,07971aef1b977295fecc687397c0e788d474d1e772d09cf614a87e7065fbb967,50,a263aa2de09fda7b9e54f2ac73be81f261827bb48d14db6bf9697ffe60be4663,f29c13793082424ae5f11e9881dffad41584b8ba4b10de22257ac93d9362d7f2 153 | 1,a263aa2de09fda7b9e54f2ac73be81f261827bb48d14db6bf9697ffe60be4663,51,b92d098772f99bff7398ef4cd52727523fe39084794a10002ac4fbfe489c7389,40e5eea16a1d0bde9aa5e944226caf045ae5d981c686907248bd2725ab8daf1b 154 | 1,b92d098772f99bff7398ef4cd52727523fe39084794a10002ac4fbfe489c7389,52,9103161066d0636798e3b94c7a7c03615602f02161f0d69664ac687ce14438cc,14eefdb5a51d323a026191bfd6d59c04224a126ed0402aa93f77782559e3d85c 155 | 1,9103161066d0636798e3b94c7a7c03615602f02161f0d69664ac687ce14438cc,53,e2430ea86943c6b64cdd28f8f2a2ad982b39571fd8dcb19b5671c14bc80760ee,055e9b90b9db29f7100b13dc9a29dfa6e93ae094bc1cb9cb4078497b0058f135 156 | 1,e2430ea86943c6b64cdd28f8f2a2ad982b39571fd8dcb19b5671c14bc80760ee,54,b3086f3d66c4a5b4f5e484de6f2433d0c8b2ed06635af3c1388e30111e305940,c429ed9f1eb3483982133ffc8125670271472ec0a554376a2f890797e4df1456 157 | 1,b3086f3d66c4a5b4f5e484de6f2433d0c8b2ed06635af3c1388e30111e305940,55,593a5a23fd48f4a2ebf75d2a90be2396b6b6c9f0c9e811da35320a2a9ad3ba84,8f38e9bc0d8fe64029510c00dae843857e1a15c3adffe507937a76431e2dfbea 158 | 1,593a5a23fd48f4a2ebf75d2a90be2396b6b6c9f0c9e811da35320a2a9ad3ba84,56,d1c56b22056f651563702acf30b32c25d22973c9a70a4dd702381edd90339920,dc6002c2e6cc3d4ffb79666daee426a40528caaf17708c06d0fbb90b6ac36576 159 | 1,d1c56b22056f651563702acf30b32c25d22973c9a70a4dd702381edd90339920,57,291385cadfcf6519e1ecb8108f16c40145753d92880c47d449a352d5f319599a,2029d05f3da003d70b5fa3e445f91d02b157516da305a45be0439ce523f56950 160 | 1,291385cadfcf6519e1ecb8108f16c40145753d92880c47d449a352d5f319599a,58,e9d2803c316f56e003e6b612ca960bf195885771b6158e210c4aa092f560c804,225d66b70635b52ae957e038b5c5110ce3c0d52901dcec54d8b4fc324098b4e2 161 | 1,e9d2803c316f56e003e6b612ca960bf195885771b6158e210c4aa092f560c804,59,00e1a6d667716d923911cebf4623659884c3cd2059c2b335e03bd533b9a20cd2,e371676213b3846dc06b54e3fe1dd41a2a0edea149823f7a34b20a2b9c5bf28c 162 | 1,00e1a6d667716d923911cebf4623659884c3cd2059c2b335e03bd533b9a20cd2,60,2bf564faaf13a02122d6ffcd76e9c88f6dd29a161d079aa931173db010645821,39306a60a3b7ecbaedc0a0b3ad436eb01a028a9445f3ffdad72c247406868e52 163 | 1,2bf564faaf13a02122d6ffcd76e9c88f6dd29a161d079aa931173db010645821,61,d18405750cddd31b8689e5d0e36636e3d1e3cc9b44a4eb1b246a88d12d1e9a04,00c0e3b9c7feb3ec1aeb8712ffe5ad8b25038dad8436c0f90294c0cbcdf2623c 164 | 1,d18405750cddd31b8689e5d0e36636e3d1e3cc9b44a4eb1b246a88d12d1e9a04,62,447054e159fc0a9af95ed677b84f185ba598c1aa8e16ae8844075a116b39acf1,3212c30ae5623ed890c0b3555a124b73568b337e31ff4039d11cc11b755c8c91 165 | 1,447054e159fc0a9af95ed677b84f185ba598c1aa8e16ae8844075a116b39acf1,63,a73cf5668500731353cd660c1f0a54cf0624ebe5576a64194e7c9068047d66e2,cc1368d2a7e25e3a3dee572d8e9f479c6711c50abb816dc79b5bf0d0f2ed554a 166 | 1,a73cf5668500731353cd660c1f0a54cf0624ebe5576a64194e7c9068047d66e2,64,a1f21612a45d111ba54bf0e0902393fe5c250e4ac68deb4a8ddada798b420e33,cc9b8c05b8e76a75f28be49c028aa46552a10843b9c2be0e2a90c3845bcd24c6 167 | 1,a1f21612a45d111ba54bf0e0902393fe5c250e4ac68deb4a8ddada798b420e33,65,f29923bcd0fe069f52065aec3059da349190f77128fa307c61a8adef6e2e352a,829a85d3ba036602d8d674e46ab92e73b077d9de806bf808b97b234dc60238fc 168 | 1,f29923bcd0fe069f52065aec3059da349190f77128fa307c61a8adef6e2e352a,66,7346fa2cbbd3e9308d79bf7df0012c56ac08229c6b2fd3485ab7122df1d2bd3c,d07e3ba2d0532a92268288d818dea759b1406ba9d48a069a382baf6447800b90 169 | 1,7346fa2cbbd3e9308d79bf7df0012c56ac08229c6b2fd3485ab7122df1d2bd3c,67,bd8dce4d494233b5ce0b224ff2a944a54beba8c739fe4d23a6e59ca4c238e536,b2c2293f74a0d130cfb6ffe4c7c50127a50c9d4b7eb458a01527e36eaa4544c4 170 | 1,bd8dce4d494233b5ce0b224ff2a944a54beba8c739fe4d23a6e59ca4c238e536,68,31683c32b06e51d21e85a0d7ae0029b42ca0e1d6b3dcd1bfc17a61c248933e92,5b25553c534f67bdb6fc155297e414560df4b085459d6cffcd9dfe5c5a44d043 171 | 1,31683c32b06e51d21e85a0d7ae0029b42ca0e1d6b3dcd1bfc17a61c248933e92,69,bb088315593ed930f9c7ad4437eb07e52e43ddaec835b01ea5664ca335e46c2a,e7d8bb629d12168b751279d95a2dfe72939f83f7010045a4ce2c3e975b588d42 172 | 1,bb088315593ed930f9c7ad4437eb07e52e43ddaec835b01ea5664ca335e46c2a,70,feacd1b4d6549c20b63bf1c1ff2ff5a1d75645b16ead4218d851a7214adf0542,fb80a0a075efabc4285970c02fdda0d649731e9ad023a01a4873c56ac467e1b4 173 | 1,feacd1b4d6549c20b63bf1c1ff2ff5a1d75645b16ead4218d851a7214adf0542,71,c55d4c1f313caaf5201c8f7ee4c01020c2c19cddb5f802d343f57b0af4ead2fc,d7f5a265af64c768178fad921d2eba0c25fa08b3928f06d0a4c945bcd0f13a34 174 | 1,c55d4c1f313caaf5201c8f7ee4c01020c2c19cddb5f802d343f57b0af4ead2fc,72,c07d18923d41ca62da41e7033fe044a551e98e2b2266d98404c4fad68dba09c8,fe38e82f809501d0fd56ca070c320bcbf3147e80cb1924fce83f2521701bccf0 175 | 1,c07d18923d41ca62da41e7033fe044a551e98e2b2266d98404c4fad68dba09c8,73,ef8264c23656bf1384dfed51b6a17f16040f905f260139763f01d8993f5ced12,8b293ce157334bf24eda4c79fb5f64bcfce35d05e9e88afc59f596b908a3426f 176 | 1,ef8264c23656bf1384dfed51b6a17f16040f905f260139763f01d8993f5ced12,74,1d4d854a6abb3e087ad3c2cb7882692e235fd3a43dbd106242dc28f65ef0492b,de5ed3a9809cb22fd969e47445c3cb5d0215b8c389448c66dbe95af3cc218945 177 | 1,1d4d854a6abb3e087ad3c2cb7882692e235fd3a43dbd106242dc28f65ef0492b,75,f41f1541851702b6db8e495232df68ec47210f0e0a7bc2273f23f4578840f8c2,0f553fe30c23d0271bd98245a8fa1bf852d1fbeac0e5962da5ee58162db3b84d 178 | 1,f41f1541851702b6db8e495232df68ec47210f0e0a7bc2273f23f4578840f8c2,76,fc918c788501b8e11438c8232f20b757fc9c9f590a915a193d92c8f4424f68a3,5e3c8bf3df1d23e6538c17505be53552be93945d27d06cef22bfb053bdaad176 179 | 1,fc918c788501b8e11438c8232f20b757fc9c9f590a915a193d92c8f4424f68a3,77,4fc2c0cda142b8a820138f3efb2379f268cdf9aeb3daad59feddf6d1831bd889,bfbbffc15694e6aea9275c44da54b070df7704081996ca9a306d07fbbdd27b60 180 | 1,4fc2c0cda142b8a820138f3efb2379f268cdf9aeb3daad59feddf6d1831bd889,78,5b6928ec00e5663a668b029c19e8cca117e64af26298e56c01729d07c2035034,d625cf478d00d99f3e5dc42383e23aca0f098656abe46fc77ac0ac285ec55a66 181 | 1,5b6928ec00e5663a668b029c19e8cca117e64af26298e56c01729d07c2035034,79,787d8bf6377aae243e114e4021c5ac8a974b2d89217cd30b75f7d94e64fcdf50,3ae5d98994a9aaed75054f8b7c65c70dc29c97569ca6dc0c39813cacf3f90a38 182 | 1,787d8bf6377aae243e114e4021c5ac8a974b2d89217cd30b75f7d94e64fcdf50,80,2592547f2d5ac8158d62248bc7bdd1c772f3128b6968bdd87dc202433f8e0ae7,acbb34c0e87df9293a2c313e3ecc86a3ff7108d3ad5c94d9d5c91ceab0793510 183 | 1,2592547f2d5ac8158d62248bc7bdd1c772f3128b6968bdd87dc202433f8e0ae7,81,afbaf0e4dff4667d462ff5d4ccbcd87bdf5b84d22d8ca874e0bdad8c9c8a741b,a8da7b4b1a7228a4245a9615e404f36b6e490bd79354b5082e1ea89d6e9094b3 184 | 1,afbaf0e4dff4667d462ff5d4ccbcd87bdf5b84d22d8ca874e0bdad8c9c8a741b,82,10c522f84ac2d64fa34df844aa8ff66e694d7b7cac83d331e371e5f89c9c45da,bc4be4bcc73157e1aeb236c43302f54ecc0cb5764cee7384862f44f5d280fc4c 185 | 1,10c522f84ac2d64fa34df844aa8ff66e694d7b7cac83d331e371e5f89c9c45da,83,297765f974424cff457dd8f2d6db338bca8255acf7dee2e2510e71e1f2699e34,97dd49a5d02f7dbde082e283fdde4b8be6f4cf7d588388fed9998990fa0a8563 186 | 1,297765f974424cff457dd8f2d6db338bca8255acf7dee2e2510e71e1f2699e34,84,fa085b9ec67ea06d2be5b9d451343914eed3a7e77f691d567336ea12068dc097,24fa073e6e3e98c7dc353cb3edf42d13a7d5975ef2dc5b2a628189979852c3cd 187 | 1,fa085b9ec67ea06d2be5b9d451343914eed3a7e77f691d567336ea12068dc097,85,532aa869e792c092cc38e4f789f883b904ef444f67880018085d69f796909561,4d53afda0429e2b6a853e0269869a39308279df07e9320867d9d5c493463ae1f 188 | 1,532aa869e792c092cc38e4f789f883b904ef444f67880018085d69f796909561,86,742bc28f8afbc4928c8b092ad256499ee0b403850853bc72cc97ecab3a60217d,384f34072180164477f285b70cade715cb151c1f802c3347c70085f4643a6ab5 189 | 1,742bc28f8afbc4928c8b092ad256499ee0b403850853bc72cc97ecab3a60217d,87,3093e60bba288c79a29c5b2cf68272f19d96a06c2873134d0f5071d4755a7e2c,bb3712a8c8a11109654c431e6299c73ddfb12120854debd9a1b29ab688a8061a 190 | 1,3093e60bba288c79a29c5b2cf68272f19d96a06c2873134d0f5071d4755a7e2c,88,3bce6faf348e4759a5c0791887913f06c1969f349daf74f3f61e2245c7df8ad2,5433a32e208dca8768ec09a6ddd1db447d04f1322844d1d3e9177f3ee22b8005 191 | 1,3bce6faf348e4759a5c0791887913f06c1969f349daf74f3f61e2245c7df8ad2,89,a8ce1d012de60058a95985c846161ab57d25ad98ab871246298a86e8a9e9900e,765ef35d89d13d91da124df1acafc32fa55d1181bedaa5eadb6ae7c1e77027d1 192 | 1,a8ce1d012de60058a95985c846161ab57d25ad98ab871246298a86e8a9e9900e,90,7a13f41447e81429e8b8e49b7d1f368991a4703861379228132f688c7da96a1f,68589af665f7e5c580f42dbb1abadd4115e9de6a55325931b0bb9c362c4496fe 193 | 1,7a13f41447e81429e8b8e49b7d1f368991a4703861379228132f688c7da96a1f,91,ea359a08d944709cde9bb1695331d420b2a32b30d0d2a5534aa34a810142ad28,a76feb795837ea99cde9d543c66736baaf60519be48e7237873f4b47af520077 194 | 1,ea359a08d944709cde9bb1695331d420b2a32b30d0d2a5534aa34a810142ad28,92,247493a40ae00bc5d7b535e93f22a0085397610527ecd0f1509c9deb034735e1,fade6d52f3e37be75ffa6032e0f7fddba0e38e92f2c314584cba1b5f7e34956f 195 | 1,247493a40ae00bc5d7b535e93f22a0085397610527ecd0f1509c9deb034735e1,93,70867944a6dc6311085616b1c975275f079c99fbf25e61b1ac86aad43d91c538,6269fed001577d20c5ec337e5ccd6bac12598e8bdce5468fec589de0607738a1 196 | 1,70867944a6dc6311085616b1c975275f079c99fbf25e61b1ac86aad43d91c538,94,9ad92fda20560ad5bc75353379c95bda5a18313797d6ee4dc0968fb950b6425d,7efce8b34157b35c4b170579ca7c0e414e79a3ea9ffe8c7cb21d38e961f67abb 197 | 1,9ad92fda20560ad5bc75353379c95bda5a18313797d6ee4dc0968fb950b6425d,95,cd029bf8435a164213b2d8e8b359a131a3b01bce3f95019f26fa9e10f37f72f5,4b14a601ba0b1712fde24930e65e1ab24dd09008a638f860e58fc2fa0ee20c44 198 | 1,cd029bf8435a164213b2d8e8b359a131a3b01bce3f95019f26fa9e10f37f72f5,96,10ca33b99ad1b750d1246e1db94f1fd9dda1c2d549c37b2fc760c14e487d9c85,d7a15f75cc337fa0450a0868bbaf11b80e65a676701f4f74fb32c4b52b123393 199 | 1,10ca33b99ad1b750d1246e1db94f1fd9dda1c2d549c37b2fc760c14e487d9c85,97,0688490b9fe3e22673f6ee04d88ff67be3f6f6f236d423864fecd96c3c203160,5fbc1d4949d1b2453764b721b9e7efd33f61b26f6d1a2bd2300e52b2ed85355c 200 | 1,0688490b9fe3e22673f6ee04d88ff67be3f6f6f236d423864fecd96c3c203160,98,a1daddff674edb2589fad5b422661821165b4ad4a7f06f510d1d0cf2e961d9f0,76ad42af40e39fb8497aedc7584e7777f42ecc95352a26b931f2b099b21ce924 201 | 1,a1daddff674edb2589fad5b422661821165b4ad4a7f06f510d1d0cf2e961d9f0,99,e44660627a5775a10d26e4fec96d87e46f91af5e79dc81bc0d37e3d493b12f85,21ae2498e5bd89d37b73b34217bd1233cdb67ee80ed0ab1dea706a4aa0cf024d 202 | -------------------------------------------------------------------------------- /libegihash/egihash.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ryan Lucchese 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "egihash.h" 6 | extern "C" 7 | { 8 | #include "keccak-tiny.h" 9 | } 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include // TODO: remove me (debugging) 24 | 25 | namespace 26 | { 27 | using namespace egihash; 28 | 29 | #pragma pack(push, 1) 30 | struct dag_file_header_t 31 | { 32 | static constexpr size_t magic_size = sizeof(constants::DAG_MAGIC_BYTES); 33 | using size_type = dag_t::size_type; 34 | 35 | char magic[magic_size]; 36 | uint32_t major_version; 37 | uint32_t revision; 38 | uint32_t minor_version; 39 | uint64_t epoch; 40 | uint64_t cache_begin; 41 | uint64_t cache_end; 42 | uint64_t dag_begin; 43 | uint64_t dag_end; 44 | 45 | dag_file_header_t() = delete; 46 | dag_file_header_t(dag_file_header_t const &) = default; 47 | dag_file_header_t & operator=(dag_file_header_t const &) = default; 48 | dag_file_header_t(dag_file_header_t &&) = default; 49 | dag_file_header_t & operator=(dag_file_header_t &&) = default; 50 | ~dag_file_header_t() = default; 51 | 52 | dag_file_header_t(read_function_type read) 53 | : magic{0} 54 | , major_version(0) 55 | , revision(0) 56 | , minor_version(0) 57 | , epoch(0) 58 | , cache_begin(0) 59 | , cache_end(0) 60 | , dag_begin(0) 61 | , dag_end(0) 62 | { 63 | read(magic, magic_size); 64 | 65 | if (std::string(magic) != constants::DAG_MAGIC_BYTES) 66 | { 67 | throw hash_exception("Not a DAG file"); 68 | } 69 | 70 | read(&major_version, sizeof(major_version)); 71 | read(&revision, sizeof(revision)); 72 | read(&minor_version, sizeof(minor_version)); 73 | if ((major_version != constants::MAJOR_VERSION) || (revision != constants::REVISION)) 74 | { 75 | throw hash_exception("DAG version is invalid"); 76 | } 77 | 78 | read(&epoch, sizeof(epoch)); 79 | read(&cache_begin, sizeof(cache_begin)); 80 | read(&cache_end, sizeof(cache_end)); 81 | read(&dag_begin, sizeof(dag_begin)); 82 | read(&dag_end, sizeof(dag_end)); 83 | 84 | // validate size of cache 85 | cache_t::size_type cache_size = cache_t::get_cache_size((epoch * constants::EPOCH_LENGTH) + 1); 86 | if ((cache_end <= cache_begin) || (cache_size != (cache_end - cache_begin))) 87 | { 88 | throw hash_exception("DAG cache is corrupt"); 89 | } 90 | 91 | // validate size of DAG 92 | uint64_t const size = dag_t::get_full_size((epoch * constants::EPOCH_LENGTH) + 1); // get the correct dag size 93 | if ((dag_end <= dag_begin) || (size != (dag_end - dag_begin))) 94 | { 95 | throw hash_exception("DAG is corrupt"); 96 | } 97 | } 98 | }; 99 | #pragma pack(pop) 100 | 101 | static_assert(dag_file_header_t::magic_size == 12, "Magic size invalid."); 102 | static_assert(sizeof(dag_file_header_t) == 64, "Dag header size invalid."); 103 | 104 | inline uint32_t decode_int(uint8_t const * data, uint8_t const * dataEnd) noexcept 105 | { 106 | if (!data || (dataEnd < (data + 3))) 107 | return 0; 108 | 109 | return static_cast( 110 | (static_cast(data[3]) << 24) | 111 | (static_cast(data[2]) << 16) | 112 | (static_cast(data[1]) << 8) | 113 | (static_cast(data[0])) 114 | ); 115 | } 116 | 117 | inline ::std::string zpad(::std::string const & str, size_t const length) 118 | { 119 | return str + ::std::string(::std::max(length - str.length(), static_cast<::std::string::size_type>(0)), 0); 120 | } 121 | 122 | template 123 | typename ::std::enable_if<::std::is_integral::value, ::std::string>::type 124 | /*::std::string*/ encode_int(IntegralType x) 125 | { 126 | using namespace std; 127 | 128 | if (x == 0) return string(); 129 | 130 | // TODO: fast hex conversion 131 | stringstream ss; 132 | ss << hex << x; 133 | string hex_str = ss.str(); 134 | string encoded(hex_str.length() % 2, '0'); 135 | encoded += hex_str; 136 | 137 | string ret; 138 | ss.str(string()); 139 | for (size_t i = encoded.size(); i >= 2; i -= 2) 140 | { 141 | ret += static_cast(stoi(encoded.substr(i - 2, 2), 0, 16)); 142 | } 143 | 144 | return ret; 145 | } 146 | 147 | template 148 | typename ::std::enable_if<::std::is_integral::value, bool>::type 149 | /*bool*/ is_prime(IntegralType x) noexcept 150 | { 151 | for (auto i = IntegralType(2); i <= ::std::sqrt(x); i++) 152 | { 153 | if ((x % i) == 0) return false; 154 | } 155 | return true; 156 | } 157 | 158 | inline uint32_t fnv(uint32_t v1, uint32_t v2) noexcept 159 | { 160 | constexpr uint32_t FNV_PRIME = 0x01000193ull; // prime number used for FNV hash function 161 | constexpr uint64_t FNV_MODULUS = 1ull << 32ull; // modulus used for FNV hash function 162 | 163 | return ((v1 * FNV_PRIME) ^ v2) % FNV_MODULUS; 164 | } 165 | 166 | template 167 | struct sha3_base 168 | { 169 | using deserialized_hash_t = ::std::vector; 170 | using size_type = ::std::size_t; 171 | 172 | static constexpr size_type hash_size = HashSize; 173 | static constexpr size_type data_size = HashSize / sizeof(node); 174 | deserialized_hash_t data; 175 | 176 | sha3_base(sha3_base const &) = default; 177 | sha3_base(sha3_base &&) = default; 178 | sha3_base & operator=(sha3_base const &) = default; 179 | sha3_base & operator=(sha3_base &&) = default; 180 | ~sha3_base() = default; 181 | 182 | sha3_base() 183 | :data(data_size) 184 | { 185 | 186 | } 187 | 188 | sha3_base(::std::string const & input) 189 | :sha3_base() 190 | { 191 | compute_hash(input.c_str(), input.size()); 192 | } 193 | 194 | sha3_base(void const * input, size_type const input_size) 195 | :sha3_base() 196 | { 197 | compute_hash(input, input_size); 198 | } 199 | 200 | inline void compute_hash(void const * input, size_type const input_size) 201 | { 202 | if (HashFunction(reinterpret_cast(data.data()), hash_size, reinterpret_cast(input), input_size) != 0) 203 | { 204 | throw hash_exception("Unable to compute hash"); // TODO: better message? 205 | } 206 | } 207 | 208 | inline deserialized_hash_t deserialize() const 209 | { 210 | return data; 211 | } 212 | 213 | inline static ::std::string serialize(deserialized_hash_t const & h) 214 | { 215 | return std::string(reinterpret_cast(h.data()), h.size() * sizeof(node)); 216 | } 217 | 218 | operator ::std::string() const 219 | { 220 | // TODO: fast hex conversion 221 | ::std::stringstream ss; 222 | ss << ::std::hex; 223 | uint8_t const * iEnd = reinterpret_cast(&data.back()); 224 | for (uint8_t const * i = reinterpret_cast(data.data()); i != iEnd; i++) 225 | { 226 | ss << ::std::setw(2) << ::std::setfill('0') << static_cast(*i); 227 | } 228 | return ss.str(); 229 | } 230 | }; 231 | 232 | struct sha3_256_t : public sha3_base<32, ::sha3_256> 233 | { 234 | sha3_256_t(::std::string const & input) 235 | : sha3_base(input) 236 | { 237 | 238 | } 239 | 240 | sha3_256_t(void const * input, size_type const input_size) 241 | : sha3_base(input, input_size) 242 | { 243 | 244 | } 245 | }; 246 | 247 | struct sha3_512_t : public sha3_base<64, ::sha3_512> 248 | { 249 | sha3_512_t(::std::string const & input) 250 | : sha3_base(input) 251 | { 252 | 253 | } 254 | 255 | sha3_512_t(void const * input, size_type const input_size) 256 | : sha3_base(input, input_size) 257 | { 258 | 259 | } 260 | }; 261 | 262 | // TODO: unit tests / validation 263 | template 264 | typename HashType::deserialized_hash_t hash_words(::std::string const & data) 265 | { 266 | return HashType(data).data; 267 | } 268 | 269 | template 270 | typename HashType::deserialized_hash_t hash_words(DataType * data_ptr, typename HashType::size_type data_size) 271 | { 272 | return HashType(data_ptr, data_size).data; 273 | } 274 | 275 | // TODO: unit tests / validation 276 | template 277 | typename HashType::deserialized_hash_t hash_words(typename HashType::deserialized_hash_t const & deserialized) 278 | { 279 | auto const serialized = HashType::serialize(deserialized); 280 | return hash_words(serialized); 281 | } 282 | 283 | template 284 | result_t hash_header_nonce(HashFunc hashfunc, DatasetType const & dataset, h256_t const & header_hash, uint64_t const nonce) 285 | { 286 | uint8_t const * nonce_bytes = reinterpret_cast(&nonce); 287 | 288 | // combine header_hash with nonce 289 | uint8_t const bytes[sizeof(header_hash.b) + sizeof(nonce)] = 290 | { 291 | header_hash.b[ 0], header_hash.b[ 1], header_hash.b[ 2], header_hash.b[ 3], 292 | header_hash.b[ 4], header_hash.b[ 5], header_hash.b[ 6], header_hash.b[ 7], 293 | header_hash.b[ 8], header_hash.b[ 9], header_hash.b[10], header_hash.b[11], 294 | header_hash.b[12], header_hash.b[13], header_hash.b[14], header_hash.b[15], 295 | header_hash.b[16], header_hash.b[17], header_hash.b[18], header_hash.b[19], 296 | header_hash.b[20], header_hash.b[21], header_hash.b[22], header_hash.b[23], 297 | header_hash.b[24], header_hash.b[25], header_hash.b[26], header_hash.b[27], 298 | header_hash.b[28], header_hash.b[29], header_hash.b[30], header_hash.b[31], 299 | 300 | nonce_bytes[0], nonce_bytes[1], nonce_bytes[2], nonce_bytes[3], 301 | nonce_bytes[4], nonce_bytes[5], nonce_bytes[6], nonce_bytes[7], 302 | }; 303 | 304 | return hashfunc(dataset, bytes, sizeof(bytes)); 305 | } 306 | } 307 | 308 | namespace egihash 309 | { 310 | constexpr h256_t::size_type h256_t::hash_size; 311 | 312 | h256_t::h256_t(void const * input_data, size_type input_size) 313 | : b{0} 314 | { 315 | if (::sha3_256(b, hash_size, reinterpret_cast(input_data), input_size) != 0) 316 | { 317 | throw hash_exception("Keccak-256 computation failed."); 318 | } 319 | } 320 | 321 | ::std::string h256_t::to_hex() const 322 | { 323 | // TODO: fast hex conversion 324 | ::std::stringstream ss; 325 | ss << ::std::hex << ::std::nouppercase; 326 | uint8_t const * iEnd = reinterpret_cast(&b[hash_size]); 327 | for (uint8_t const * i = reinterpret_cast(&b[0]); i != iEnd; i++) 328 | { 329 | ss << ::std::setw(2) << ::std::setfill('0') << static_cast(*i); 330 | } 331 | return ss.str(); 332 | } 333 | 334 | h256_t::operator bool() const 335 | { 336 | return (::std::memcmp(&b[0], &empty_h256.b[0], sizeof(b)) != 0); 337 | } 338 | 339 | bool h256_t::operator==(h256_t const & rhs) const 340 | { 341 | return (::std::memcmp(&b[0], &rhs.b[0], sizeof(b)) == 0); 342 | } 343 | 344 | constexpr h512_t::size_type h512_t::hash_size; 345 | 346 | h512_t::h512_t(void const * input_data, size_type input_size) 347 | : b{0} 348 | { 349 | if (::sha3_512(b, hash_size, reinterpret_cast(input_data), input_size) != 0) 350 | { 351 | throw hash_exception("Keccak-512 computation failed."); 352 | } 353 | } 354 | 355 | ::std::string h512_t::to_hex() const 356 | { 357 | // TODO: fast hex conversion 358 | ::std::stringstream ss; 359 | ss << ::std::hex << ::std::nouppercase; 360 | uint8_t const * iEnd = reinterpret_cast(&b[hash_size]); 361 | for (uint8_t const * i = reinterpret_cast(&b[0]); i != iEnd; i++) 362 | { 363 | ss << ::std::setw(2) << ::std::setfill('0') << static_cast(*i); 364 | } 365 | return ss.str(); 366 | } 367 | 368 | h512_t::operator bool() const 369 | { 370 | return (::std::memcmp(&b[0], &empty_h512.b[0], sizeof(b)) != 0); 371 | } 372 | 373 | bool h512_t::operator==(h512_t const & rhs) const 374 | { 375 | return (::std::memcmp(&b[0], &rhs.b[0], sizeof(b)) == 0); 376 | } 377 | 378 | result_t::operator bool() const 379 | { 380 | return bool(value) && bool(mixhash); 381 | } 382 | 383 | bool result_t::operator==(result_t const & rhs) const 384 | { 385 | return ((value == rhs.value) && (mixhash == rhs.mixhash)); 386 | } 387 | 388 | // TODO: unit tests / validation 389 | template 390 | sha3_512_t::deserialized_hash_t sha3_512(T const & data) 391 | { 392 | return hash_words(data); 393 | } 394 | 395 | template 396 | sha3_512_t::deserialized_hash_t sha3_512(DataPtr const * data, sha3_512_t::size_type data_size) 397 | { 398 | return hash_words(data, data_size); 399 | } 400 | 401 | // TODO: unit tests / validation 402 | template 403 | sha3_256_t::deserialized_hash_t sha3_256(T const & data) 404 | { 405 | return hash_words(data); 406 | } 407 | 408 | template 409 | sha3_256_t::deserialized_hash_t sha3_256(DataPtr const * data, sha3_256_t::size_type data_size) 410 | { 411 | return hash_words(data, data_size); 412 | } 413 | 414 | // TODO: unit tests / validation 415 | template 416 | ::std::string serialize_cache(T const & cache_data) 417 | { 418 | ::std::string ret; 419 | for (auto const & i : cache_data) 420 | { 421 | ret += serialize_hash(cache_data); 422 | } 423 | return ret; 424 | } 425 | 426 | // TODO: unit tests / validation 427 | template 428 | ::std::string serialize_dataset(T const & dataset) 429 | { 430 | return serialize_cache(dataset); 431 | } 432 | 433 | struct cache_t::impl_t 434 | { 435 | using size_type = cache_t::size_type; 436 | using data_type = ::std::vector>; 437 | using cache_cache_map = ::std::map>; 438 | 439 | impl_t(uint64_t const block_number, progress_callback_type callback) 440 | : epoch(block_number / constants::EPOCH_LENGTH) 441 | , seedhash(get_seedhash(block_number)) 442 | , size(get_cache_size(block_number)) 443 | , data() 444 | { 445 | mkcache(callback); 446 | } 447 | 448 | impl_t(uint64_t epoch, uint64_t size, read_function_type read, progress_callback_type callback) 449 | : epoch(epoch) 450 | , seedhash(get_seedhash((epoch * constants::EPOCH_LENGTH) + 1)) 451 | , size(size) 452 | , data() 453 | { 454 | load(read, callback); 455 | } 456 | 457 | void mkcache(progress_callback_type callback) 458 | { 459 | uint32_t n = size / constants::HASH_BYTES; 460 | 461 | data.reserve(n); 462 | data.push_back(sha3_512(&seedhash.b[0], seedhash.hash_size)); 463 | for (uint32_t i = 1; i < n; i++) 464 | { 465 | data.push_back(sha3_512(data.back())); 466 | if (((i % constants::CALLBACK_FREQUENCY) == 0) && !callback(i, n, cache_seeding)) 467 | { 468 | throw hash_exception("Cache creation cancelled."); 469 | } 470 | } 471 | 472 | //std::cout << "Length: " << data.size() << std::endl; 473 | 474 | uint32_t progress_counter = 0; 475 | for (uint32_t i = 0; i < constants::CACHE_ROUNDS; i++) 476 | { 477 | for (uint32_t j = 0; j < n; j++) 478 | { 479 | auto v = data[j][0].hword % n; 480 | auto u = data[(n - 1 + j)%n]; 481 | size_t count = 0; 482 | for (auto & k : u) 483 | { 484 | k.hword = k.hword ^ data[v][count++].hword; 485 | } 486 | data[j] = sha3_512(u); 487 | 488 | if (((++progress_counter % constants::CALLBACK_FREQUENCY) == 0) && !callback(progress_counter, n * constants::CACHE_ROUNDS, cache_generation)) 489 | { 490 | throw hash_exception("Cache creation cancelled."); 491 | } 492 | } 493 | } 494 | } 495 | 496 | void load(read_function_type read, progress_callback_type callback) 497 | { 498 | size_type const cache_hash_count = size / constants::HASH_BYTES; 499 | 500 | data.resize(cache_hash_count); 501 | size_t count = 0; 502 | for (auto & i : data) 503 | { 504 | i.resize(constants::HASH_BYTES / constants::WORD_BYTES); 505 | read(&i[0], constants::HASH_BYTES); 506 | if (((++count % constants::CALLBACK_FREQUENCY) == 0) && !callback(count, cache_hash_count, cache_loading)) 507 | { 508 | throw hash_exception("Cache loading cancelled."); 509 | } 510 | } 511 | } 512 | 513 | static size_type get_cache_size(uint64_t block_number) noexcept 514 | { 515 | using namespace constants; 516 | 517 | size_type cache_size = (CACHE_BYTES_INIT + (CACHE_BYTES_GROWTH * (block_number / EPOCH_LENGTH))) - HASH_BYTES; 518 | while (!is_prime(cache_size / HASH_BYTES)) 519 | { 520 | cache_size -= (2 * HASH_BYTES); 521 | } 522 | return cache_size; 523 | } 524 | 525 | static h256_t get_seedhash(uint64_t const block_number) 526 | { 527 | ::std::string s(epoch0_seedhash, size_epoch0_seedhash); 528 | for (size_t i = 0; i < (block_number / constants::EPOCH_LENGTH); i++) 529 | { 530 | s = sha3_256_t::serialize(sha3_256(s)); 531 | } 532 | h256_t ret; 533 | ::std::memcpy(&ret.b[0], s.c_str(), (std::min)(ret.hash_size, s.length())); 534 | return ret; 535 | } 536 | 537 | uint64_t epoch; 538 | h256_t seedhash; 539 | size_type size; 540 | data_type data; 541 | }; 542 | 543 | // construct on first use mutex ensures safe static initialization order 544 | std::recursive_mutex & get_cache_cache_mutex() 545 | { 546 | static std::recursive_mutex mutex; 547 | return mutex; 548 | } 549 | // ensures single threaded construction 550 | std::recursive_mutex & cache_cache_mutex = get_cache_cache_mutex(); 551 | 552 | // construct on first use dag_cache_map ensures safe static initialization order 553 | cache_t::impl_t::cache_cache_map & get_cache_cache() 554 | { 555 | std::lock_guard lock(get_cache_cache_mutex()); 556 | static cache_t::impl_t::cache_cache_map cache_cache; 557 | return cache_cache; 558 | } 559 | // ensures single threaded construction 560 | cache_t::impl_t::cache_cache_map & cache_cache = get_cache_cache(); 561 | 562 | void cache_t::unload() const 563 | { 564 | get_cache_cache().erase(epoch()); 565 | } 566 | 567 | ::std::shared_ptr get_cache_from_cache(uint64_t const block_number, progress_callback_type callback) 568 | { 569 | using namespace std; 570 | uint64_t epoch_number = block_number / constants::EPOCH_LENGTH; 571 | 572 | // if we have the correct cache already loaded, return it from the cache cache 573 | { 574 | lock_guard lock(get_cache_cache_mutex()); 575 | auto const cache_cache_iterator = get_cache_cache().find(epoch_number); 576 | if (cache_cache_iterator != get_cache_cache().end()) 577 | { 578 | return cache_cache_iterator->second; 579 | } 580 | } 581 | 582 | // otherwise create the cache and add it to the cache cache 583 | // this is not locked as it can be a lengthy process and we don't want to block access to the cache cache 584 | shared_ptr impl(new cache_t::impl_t(block_number, callback)); 585 | 586 | lock_guard lock(get_cache_cache_mutex()); 587 | auto insert_pair = get_cache_cache().insert(make_pair(epoch_number, impl)); 588 | 589 | // if insert succeded, return the cache 590 | if (insert_pair.second) 591 | { 592 | return insert_pair.first->second; 593 | } 594 | 595 | // if insert failed, it's probably already been inserted 596 | auto const cache_cache_iterator = get_cache_cache().find(epoch_number); 597 | if (cache_cache_iterator != get_cache_cache().end()) 598 | { 599 | return cache_cache_iterator->second; 600 | } 601 | 602 | // we couldn't insert it and it's not in the cache 603 | throw hash_exception("Could not get cache"); 604 | } 605 | 606 | cache_t::cache_t(uint64_t const block_number, progress_callback_type callback) 607 | : impl(get_cache_from_cache(block_number, callback)) 608 | { 609 | } 610 | 611 | cache_t::cache_t(uint64_t epoch, uint64_t size, read_function_type read, progress_callback_type callback) 612 | : impl(new impl_t(epoch, size, read, callback)) 613 | { 614 | } 615 | 616 | uint64_t cache_t::epoch() const 617 | { 618 | return impl->epoch; 619 | } 620 | 621 | cache_t::size_type cache_t::size() const 622 | { 623 | return impl->size; 624 | } 625 | 626 | cache_t::data_type const & cache_t::data() const 627 | { 628 | return impl->data; 629 | } 630 | 631 | h256_t cache_t::seedhash() const 632 | { 633 | return impl->seedhash; 634 | } 635 | 636 | void cache_t::load(read_function_type read, progress_callback_type callback) 637 | { 638 | impl->load(read, callback); 639 | } 640 | 641 | cache_t::size_type cache_t::get_cache_size(uint64_t const block_number) noexcept 642 | { 643 | return impl_t::get_cache_size(block_number); 644 | } 645 | 646 | h256_t cache_t::get_seedhash(uint64_t const block_number) 647 | { 648 | return impl_t::get_seedhash(block_number); 649 | } 650 | 651 | bool cache_t::is_loaded(uint64_t const epoch) 652 | { 653 | using namespace std; 654 | lock_guard lock(get_cache_cache_mutex()); 655 | auto const & cache_cache = get_cache_cache(); 656 | return (cache_cache.find(epoch) != cache_cache.end()); 657 | } 658 | 659 | ::std::vector cache_t::get_loaded() 660 | { 661 | using namespace std; 662 | lock_guard lock(get_cache_cache_mutex()); 663 | auto const & cache_cache = get_cache_cache(); 664 | ::std::vector loaded_epochs; 665 | loaded_epochs.reserve(cache_cache.size()); 666 | for (auto const & i : cache_cache) 667 | { 668 | loaded_epochs.push_back(i.first); 669 | } 670 | return loaded_epochs; 671 | } 672 | 673 | struct dag_t::impl_t 674 | { 675 | using size_type = dag_t::size_type; 676 | using data_type = ::std::vector<::std::vector>; 677 | using dag_cache_map = ::std::map>; 678 | static constexpr uint64_t max_epoch = ::std::numeric_limits::max(); 679 | 680 | impl_t(uint64_t block_number, progress_callback_type callback) 681 | : epoch(block_number / constants::EPOCH_LENGTH) 682 | , size(get_full_size(block_number)) 683 | , cache(block_number, callback) 684 | , data() 685 | { 686 | generate(callback); 687 | } 688 | 689 | impl_t(read_function_type read, dag_file_header_t & header, progress_callback_type callback) 690 | : epoch(header.epoch) 691 | , size(header.dag_end - header.dag_begin) 692 | , cache(header.epoch, header.cache_end - header.cache_begin, read, callback) 693 | , data() 694 | { 695 | // load the DAG 696 | size_type dag_hash_count = size / constants::HASH_BYTES; 697 | data.resize(dag_hash_count); 698 | size_t count = 0; 699 | for (auto & i : data) 700 | { 701 | i.resize(constants::HASH_BYTES / constants::WORD_BYTES); 702 | read(&i[0], constants::HASH_BYTES); 703 | if (((++count % constants::CALLBACK_FREQUENCY) == 0) && !callback(count, data.size(), dag_loading)) 704 | { 705 | throw hash_exception("DAG loading cancelled."); 706 | } 707 | } 708 | } 709 | 710 | void save(::std::string const & file_path, progress_callback_type callback) const 711 | { 712 | using namespace std; 713 | ofstream fs; 714 | fs.open(file_path, ios::out | ios::binary); 715 | 716 | uint64_t cache_begin = constants::DAG_FILE_HEADER_SIZE + 1; 717 | uint64_t cache_end = cache_begin + cache.size(); 718 | uint64_t dag_begin = cache_end; 719 | uint64_t dag_end = dag_begin + size; 720 | 721 | auto write = [&fs](void const * data, size_type count) 722 | { 723 | // TODO: write all value in little endian 724 | fs.write(reinterpret_cast(data), count); 725 | if (fs.fail()) 726 | { 727 | throw hash_exception("Write failure"); 728 | } 729 | }; 730 | 731 | write(constants::DAG_MAGIC_BYTES, sizeof(constants::DAG_MAGIC_BYTES)); 732 | write(&constants::MAJOR_VERSION, sizeof(constants::MAJOR_VERSION)); 733 | write(&constants::REVISION, sizeof(constants::REVISION)); 734 | write(&constants::MINOR_VERSION, sizeof(constants::MINOR_VERSION)); 735 | write(&epoch, sizeof(epoch)); 736 | write(&cache_begin, sizeof(cache_begin)); 737 | write(&cache_end, sizeof(cache_end)); 738 | write(&dag_begin, sizeof(dag_begin)); 739 | write(&dag_end, sizeof(dag_end)); 740 | 741 | size_t max_count = cache.size() + data.size(); 742 | size_t count = 0; 743 | for (auto const & i : cache.data()) 744 | { 745 | for (auto const & j : i) 746 | { 747 | write(&j, sizeof(j)); 748 | } 749 | if (((++count % constants::CALLBACK_FREQUENCY) == 0) && !callback(count, max_count, dag_saving)) 750 | { 751 | throw hash_exception("DAG save cancelled."); 752 | } 753 | } 754 | 755 | for (auto const & i : data) 756 | { 757 | for (auto const & j : i) 758 | { 759 | write(&j, sizeof(j)); 760 | } 761 | if (((++count % constants::CALLBACK_FREQUENCY) == 0) && !callback(count, max_count, dag_saving)) 762 | { 763 | throw hash_exception("DAG save cancelled."); 764 | } 765 | } 766 | } 767 | 768 | void generate(progress_callback_type callback) 769 | { 770 | uint32_t const n = size / constants::HASH_BYTES; 771 | data.reserve(n); 772 | for (uint32_t i = 0; i < n; i++) 773 | { 774 | data.push_back(calc_dataset_item(cache.data(), i)); 775 | if ((i % constants::CALLBACK_FREQUENCY) == 0 && !callback(i, n, dag_generation)) 776 | { 777 | throw hash_exception("DAG creation cancelled."); 778 | } 779 | } 780 | } 781 | 782 | static data_type::value_type calc_dataset_item(::std::vector const & cache, uint32_t const i) 783 | { 784 | uint32_t const n = cache.size(); 785 | constexpr uint32_t r = constants::HASH_BYTES / constants::WORD_BYTES; 786 | sha3_512_t::deserialized_hash_t mix(cache[i%n]); 787 | mix[0].hword ^= i; 788 | mix = sha3_512(mix); 789 | for (uint32_t j = 0; j < constants::DATASET_PARENTS; j++) 790 | { 791 | uint32_t const cache_index = fnv(i ^ j, mix[j % r].hword); 792 | auto lBeg = cache[cache_index % n].begin(); 793 | auto lEnd = cache[cache_index % n].end(); 794 | for (auto k = mix.begin(), kEnd = mix.end(); 795 | ((k != kEnd) && (lBeg != lEnd)); k++, lBeg++) 796 | { 797 | k->hword = fnv(k->hword, lBeg->hword); 798 | } 799 | 800 | } 801 | return sha3_512(mix); 802 | } 803 | 804 | cache_t get_cache() const 805 | { 806 | return cache; 807 | } 808 | 809 | static size_type get_full_size(uint64_t const block_number) noexcept 810 | { 811 | using namespace constants; 812 | 813 | uint64_t full_size = (DATASET_BYTES_INIT + (DATASET_BYTES_GROWTH * (block_number / EPOCH_LENGTH))) - MIX_BYTES; 814 | while (!is_prime(full_size / MIX_BYTES)) 815 | { 816 | full_size -= (2 * MIX_BYTES); 817 | } 818 | return full_size; 819 | } 820 | 821 | uint64_t epoch; 822 | size_type size; 823 | cache_t cache; 824 | data_type data; 825 | }; 826 | 827 | // construct on first use mutex ensures safe static initialization order 828 | std::recursive_mutex & get_dag_cache_mutex() 829 | { 830 | static std::recursive_mutex mutex; 831 | return mutex; 832 | } 833 | // ensures single threaded construction 834 | std::recursive_mutex & dag_cache_mutex = get_dag_cache_mutex(); 835 | 836 | // construct on first use dag_cache_map ensures safe static initialization order 837 | dag_t::impl_t::dag_cache_map & get_dag_cache() 838 | { 839 | std::lock_guard lock(get_dag_cache_mutex()); 840 | static dag_t::impl_t::dag_cache_map dag_cache; 841 | return dag_cache; 842 | } 843 | // ensures single threaded construction 844 | dag_t::impl_t::dag_cache_map & dag_cache = get_dag_cache(); 845 | 846 | ::std::shared_ptr get_dag(uint64_t block_number, progress_callback_type callback) 847 | { 848 | using namespace std; 849 | uint64_t epoch_number = block_number / constants::EPOCH_LENGTH; 850 | 851 | // if we have the correct DAG already loaded, return it from the cache 852 | { 853 | lock_guard lock(get_dag_cache_mutex()); 854 | auto const dag_cache_iterator = get_dag_cache().find(epoch_number); 855 | if (dag_cache_iterator != get_dag_cache().end()) 856 | { 857 | return dag_cache_iterator->second; 858 | } 859 | } 860 | 861 | // otherwise create the dag and add it to the cache 862 | // this is not locked as it can be a lengthy process and we don't want to block access to the dag cache 863 | shared_ptr impl(new dag_t::impl_t(block_number, callback)); 864 | 865 | lock_guard lock(get_dag_cache_mutex()); 866 | auto insert_pair = get_dag_cache().insert(make_pair(epoch_number, impl)); 867 | 868 | // if insert succeded, return the dag 869 | if (insert_pair.second) 870 | { 871 | return insert_pair.first->second; 872 | } 873 | 874 | // if insert failed, it's probably already been inserted 875 | auto const dag_cache_iterator = get_dag_cache().find(epoch_number); 876 | if (dag_cache_iterator != get_dag_cache().end()) 877 | { 878 | return dag_cache_iterator->second; 879 | } 880 | 881 | // we couldn't insert it and it's not in the cache 882 | throw hash_exception("Could not get DAG"); 883 | } 884 | 885 | ::std::shared_ptr get_dag(::std::string const & file_path, progress_callback_type callback) 886 | { 887 | using namespace std; 888 | using size_type = dag_t::size_type; 889 | 890 | ifstream fs; 891 | fs.open(file_path, ios::in | ios::binary); 892 | 893 | if (fs.fail()) 894 | { 895 | throw hash_exception("Could not open DAG file."); 896 | } 897 | 898 | fs.seekg(0, ios::end); 899 | dag_t::size_type const filesize = static_cast(fs.tellg()); 900 | fs.seekg(0, ios::beg); 901 | 902 | // check minimum dag size 903 | if (filesize < constants::DAG_FILE_MINIMUM_SIZE) 904 | { 905 | throw hash_exception("DAG is corrupt"); 906 | } 907 | 908 | // data for 64MiB reads 909 | // 64MiB was chosen as it is divisible by the constants::CACHE_BYTES_GROWTH and the constants::DATASET_BYTES_GROWTH 910 | vector read_buffer(64 * 1024 * 1024, 0); 911 | auto buffer_ptr = &read_buffer[0]; 912 | auto buffer_ptr_end = &read_buffer.back() + 1; 913 | // prime the buffer 914 | fs.read(buffer_ptr, read_buffer.size()); 915 | if (fs.fail() && !fs.eof()) 916 | { 917 | throw hash_exception("Read failure"); 918 | } 919 | 920 | // TODO: this func needs to be made endian safe 921 | auto read = [&fs, &read_buffer, &buffer_ptr, &buffer_ptr_end](void * dst, size_type count) 922 | { 923 | // full buffer consumed exactly 924 | if ((buffer_ptr_end - buffer_ptr) == 1) 925 | { 926 | fs.read(&read_buffer[0], read_buffer.size()); 927 | if (fs.fail() && !fs.eof()) 928 | { 929 | throw hash_exception("Read failure"); 930 | } 931 | buffer_ptr = &read_buffer[0]; 932 | } 933 | 934 | // need to consume part of the buffer and then read more 935 | if (count > static_cast(buffer_ptr_end - buffer_ptr)) 936 | { 937 | //::std::cout << ::std::endl << "hit boundary, asked for " << count << " bytes but " << buffer_ptr_end - buffer_ptr << " remaining in buffer." << ::std::endl; 938 | ::std::memcpy(dst, buffer_ptr, buffer_ptr_end - buffer_ptr); 939 | count -= (buffer_ptr_end - buffer_ptr); 940 | dst = reinterpret_cast(dst) + (buffer_ptr_end - buffer_ptr); 941 | 942 | fs.read(&read_buffer[0], read_buffer.size()); 943 | if (fs.fail() && !fs.eof()) 944 | { 945 | throw hash_exception("Read failure"); 946 | } 947 | buffer_ptr = &read_buffer[0]; 948 | } 949 | 950 | // copy from the buffer 951 | ::std::memcpy(dst, buffer_ptr, count); 952 | buffer_ptr += count; 953 | }; 954 | 955 | dag_file_header_t header(read); 956 | 957 | if ((header.cache_end >= filesize) || (header.dag_end > (filesize + 1))) 958 | { 959 | throw hash_exception("DAG is corrupt"); 960 | } 961 | 962 | // if we have the correct DAG already loaded, return it from the cache 963 | { 964 | lock_guard lock(get_dag_cache_mutex()); 965 | auto const dag_cache_iterator = get_dag_cache().find(header.epoch); 966 | if (dag_cache_iterator != get_dag_cache().end()) 967 | { 968 | return dag_cache_iterator->second; 969 | } 970 | } 971 | 972 | // otherwise create the dag and add it to the cache 973 | // this is not locked as it can be a lengthy process and we don't want to block access to the dag cache 974 | shared_ptr impl(new dag_t::impl_t(read, header, callback)); 975 | 976 | lock_guard lock(get_dag_cache_mutex()); 977 | auto insert_pair = get_dag_cache().insert(make_pair(header.epoch, impl)); 978 | 979 | // if insert succeded, return the dag 980 | if (insert_pair.second) 981 | { 982 | return insert_pair.first->second; 983 | } 984 | 985 | // if insert failed, it's probably already been inserted 986 | auto const dag_cache_iterator = get_dag_cache().find(header.epoch); 987 | if (dag_cache_iterator != get_dag_cache().end()) 988 | { 989 | return dag_cache_iterator->second; 990 | } 991 | 992 | // we couldn't insert it and it's not in the cache 993 | throw hash_exception("Could not get DAG"); 994 | } 995 | 996 | dag_t::dag_t(uint64_t block_number, progress_callback_type callback) 997 | : impl(get_dag(block_number, callback)) 998 | { 999 | } 1000 | 1001 | dag_t::dag_t(::std::string const & file_path, progress_callback_type callback) 1002 | : impl(get_dag(file_path, callback)) 1003 | { 1004 | 1005 | } 1006 | 1007 | uint64_t dag_t::epoch() const 1008 | { 1009 | return impl->epoch; 1010 | } 1011 | 1012 | dag_t::size_type dag_t::size() const 1013 | { 1014 | return impl->size; 1015 | } 1016 | 1017 | dag_t::data_type const & dag_t::data() const 1018 | { 1019 | return impl->data; 1020 | } 1021 | 1022 | void dag_t::save(::std::string const & file_path, progress_callback_type callback) const 1023 | { 1024 | impl->save(file_path, callback); 1025 | } 1026 | 1027 | cache_t dag_t::get_cache() const 1028 | { 1029 | return impl->get_cache(); 1030 | } 1031 | 1032 | void dag_t::unload() const 1033 | { 1034 | auto const i = get_dag_cache().erase(epoch()); 1035 | if (i == 0) 1036 | { 1037 | throw hash_exception("Can not unload DAG - not loaded."); 1038 | } 1039 | get_cache().unload(); 1040 | } 1041 | 1042 | dag_t::size_type dag_t::get_full_size(uint64_t const block_number) noexcept 1043 | { 1044 | return impl_t::get_full_size(block_number); 1045 | } 1046 | 1047 | bool dag_t::is_loaded(uint64_t const epoch) 1048 | { 1049 | using namespace std; 1050 | lock_guard lock(get_dag_cache_mutex()); 1051 | auto const & dag_cache = get_dag_cache(); 1052 | return (dag_cache.find(epoch) != dag_cache.end()); 1053 | } 1054 | 1055 | ::std::vector dag_t::get_loaded() 1056 | { 1057 | using namespace std; 1058 | lock_guard lock(get_dag_cache_mutex()); 1059 | auto const & dag_cache = get_dag_cache(); 1060 | ::std::vector loaded_epochs; 1061 | loaded_epochs.reserve(dag_cache.size()); 1062 | for (auto const & i : dag_cache) 1063 | { 1064 | loaded_epochs.push_back(i.first); 1065 | } 1066 | return loaded_epochs; 1067 | } 1068 | 1069 | // TODO: reference code, remove me 1070 | #if 0 1071 | // TODO: unit tests / validation 1072 | result_t hashimoto(sha3_256_t::deserialized_hash_t const & header, uint64_t const nonce, size_t const full_size, ::std::function lookup) 1073 | { 1074 | auto const n = full_size / constants::HASH_BYTES; 1075 | auto const w = constants::MIX_BYTES / constants::WORD_BYTES; 1076 | auto const mixhashes = constants::MIX_BYTES / constants::HASH_BYTES; 1077 | 1078 | sha3_256_t::deserialized_hash_t header_seed(header); 1079 | for (size_t i = 0; i < 8; i++) 1080 | { 1081 | // TODO: nonce is big endian, this converts to little endian (do something sensible for big endian) 1082 | header_seed.push_back(reinterpret_cast(&nonce)[7 - i]); 1083 | } 1084 | auto s = sha3_512(header_seed); 1085 | decltype(s) mix; 1086 | for (size_t i = 0; i < (constants::MIX_BYTES / constants::HASH_BYTES); i++) 1087 | { 1088 | mix.insert(mix.end(), s.begin(), s.end()); 1089 | } 1090 | 1091 | for (size_t i = 0; i < constants::ACCESSES; i++) 1092 | { 1093 | auto p = fnv(i ^ s[0], mix[i % w]) % (n / mixhashes) * mixhashes; 1094 | decltype(s) newdata; 1095 | for (size_t j = 0; j < (constants::MIX_BYTES / constants::HASH_BYTES); j++) 1096 | { 1097 | auto const & h = lookup(p + j); 1098 | newdata.insert(newdata.end(), h.begin(), h.end()); 1099 | } 1100 | for (auto j = mix.begin(), jEnd = mix.end(), k = newdata.begin(), kEnd = newdata.end(); j != jEnd && k != kEnd; j++, k++) 1101 | { 1102 | *j = fnv(*j, *k); 1103 | } 1104 | } 1105 | 1106 | decltype(s) cmix; 1107 | for (size_t i = 0; i < mix.size(); i += 4) 1108 | { 1109 | cmix.push_back(fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3])); 1110 | } 1111 | 1112 | auto v = sha3_256(s); 1113 | result_t out; 1114 | ::std::memcpy(&out.value.b[0], &v[0], ::std::min(sizeof(out.value.b), v.size())); 1115 | ::std::memcpy(&out.mixhash.b[0], &cmix[0], ::std::min(sizeof(out.mixhash.b), cmix.size())); 1116 | return out; 1117 | 1118 | //::std::shared_ptr shared_mix(::std::make_shared(std::move(cmix))); 1119 | //::std::map<::std::string, decltype(shared_mix)> out; 1120 | //out.insert(decltype(out)::value_type(::std::string("mix digest"), shared_mix)); 1121 | //s.insert(s.end(), shared_mix->begin(), shared_mix->end()); 1122 | //out.insert(decltype(out)::value_type(::std::string("result"), ::std::make_shared(sha3_256(s)))); 1123 | //return out; 1124 | } 1125 | 1126 | // TODO: unit tests / validation 1127 | result_t hashimoto_light(size_t const full_size, cache_t const & c, sha3_256_t::deserialized_hash_t const & header, uint64_t const nonce) 1128 | { 1129 | return hashimoto(header, nonce, full_size, [c](size_t const x){return dag_t::impl_t::calc_dataset_item(c.data(), x);}); 1130 | } 1131 | 1132 | // TODO: unit tests / validation 1133 | result_t hashimoto_full(size_t const full_size, dag_t const & dataset, sha3_256_t::deserialized_hash_t const & header, uint64_t const nonce) 1134 | { 1135 | return hashimoto(header, nonce, full_size, [dataset](size_t const x){return dataset.data()[x];}); 1136 | } 1137 | #endif // 0 1138 | 1139 | // TODO: unify light & full implementation 1140 | namespace hashimoto 1141 | { 1142 | using mediator_get_dag_size = std::function; 1143 | using mediator_get_dag_item = std::function const (uint32_t index)>; 1144 | 1145 | result_t hash(void const * input_data, dag_t::size_type input_size, mediator_get_dag_size get_dag_size, mediator_get_dag_item get_dag_item) 1146 | { 1147 | static constexpr auto w = constants::MIX_BYTES / constants::WORD_BYTES; 1148 | auto MIXNODES = (constants::MIX_BYTES / constants::HASH_BYTES); 1149 | 1150 | auto s = sha3_512(std::string(static_cast(input_data), input_size)); 1151 | decltype(s) mix; 1152 | for (uint32_t i = 0; i < MIXNODES; i++) 1153 | { 1154 | mix.insert(mix.end(), s.begin(), s.end()); 1155 | } 1156 | 1157 | uint32_t const full_page_count = (uint32_t) ( get_dag_size() / constants::MIX_BYTES ); 1158 | for (uint32_t i = 0; i < constants::ACCESSES; i++) 1159 | { 1160 | auto p = fnv(i ^ s[0].hword, mix[i % w].hword) % full_page_count; 1161 | for (uint32_t j = 0; j < MIXNODES; j++) 1162 | { 1163 | auto h = get_dag_item(p * MIXNODES + j); 1164 | auto k = h.begin(), kEnd = h.end(); 1165 | for (auto m = mix.begin() + j * w / 2, mEnd = mix.begin() + ( j + 1 ) * w / 2; m != mEnd && k != kEnd; m++, k++) 1166 | { 1167 | m->hword = fnv(m->hword, k->hword); 1168 | } 1169 | } 1170 | } 1171 | 1172 | decltype(s) cmix; 1173 | for (uint32_t i = 0; i < mix.size(); i += 4) 1174 | { 1175 | cmix.push_back(node(fnv(fnv(fnv(mix[i].hword, mix[i+1].hword), mix[i+2].hword), mix[i+3].hword))); 1176 | } 1177 | 1178 | auto combined = std::move(s); 1179 | combined.insert(combined.end(), cmix.begin(), cmix.end()); 1180 | auto v = sha3_256(combined); 1181 | result_t out; 1182 | ::std::memcpy(&out.value.b[0], &v[0], ::std::min(sizeof(out.value.b), v.size() * sizeof(node))); 1183 | ::std::memcpy(&out.mixhash.b[0], &cmix[0], ::std::min(sizeof(out.mixhash.b), cmix.size() * sizeof(node))); 1184 | return out; 1185 | } 1186 | } 1187 | namespace full 1188 | { 1189 | 1190 | 1191 | result_t hash(dag_t const & dag, void const * input_data, dag_t::size_type input_size) 1192 | { 1193 | return hashimoto::hash(input_data, input_size 1194 | , [&]() -> dag_t::size_type { return dag.size(); } 1195 | , [&](uint32_t index) -> std::vector const { return dag.data()[index]; }); 1196 | } 1197 | result_t hash(dag_t const & dag, h256_t const & header_hash, uint64_t const nonce) 1198 | { 1199 | std::function hash_func = static_cast(&hash); 1200 | return hash_header_nonce(hash_func, dag, header_hash, nonce); 1201 | } 1202 | } 1203 | 1204 | namespace light 1205 | { 1206 | result_t hash(cache_t const & cache, void const * input_data, cache_t::size_type input_size) 1207 | { 1208 | return hashimoto::hash(input_data, input_size 1209 | , [&]() -> dag_t::size_type { return dag_t::get_full_size((cache.epoch() * constants::EPOCH_LENGTH)); } 1210 | , [&](uint32_t index) -> std::vector const { return dag_t::impl_t::calc_dataset_item(cache.data(), index); }); 1211 | } 1212 | 1213 | result_t hash(cache_t const & cache, h256_t const & header_hash, uint64_t const nonce) 1214 | { 1215 | std::function hash_func = static_cast(&hash); 1216 | return hash_header_nonce(hash_func, cache, header_hash, nonce); 1217 | } 1218 | } 1219 | 1220 | bool test_function_() 1221 | { 1222 | using namespace std; 1223 | 1224 | string base_str("this is some test data to be hashed. "); 1225 | string input_str(base_str); 1226 | vector> sixtyfour_results; 1227 | vector> thirtytwo_results; 1228 | 1229 | for (size_t i = 0; i < 10; i++) 1230 | { 1231 | input_str += base_str; 1232 | // TODO: make_unique requires c++14 1233 | //sixtyfour_results.push_back(make_unique(input_str)); 1234 | //thirtytwo_results.push_back(make_unique(input_str)); 1235 | } 1236 | 1237 | // compare to known values 1238 | static vector const sixtyfour_expected = { 1239 | "24f586494157502950fdd5097f77f7c7e9246744a155f75cfa6a80f23a1819e57eccdba39955869a8fb3a30a3536b5f9602b40c1660c446749a8b56f2649142c", 1240 | "a8d1f26010dd21fb82f1ba96e04dd6d31ecd67cb8f1a2154a39372b3a195a91ee01006f723da488dc12e49c499d63828d1ff9f5f8bfe64084191865151616eaa", 1241 | "dbe6ead2b1a7ddd74e5de9898e9fa1daad9d754cdb407b9a5682d2a9dffe4cd3fa9c86426f2d76b8f8ba176e5b1cc260ebca4ce4d9bd50e9d547a322de58c3ec", 1242 | "b8c51bc171966c32bd9f322f2aefdd133bae9b5e562628861f04ddb52461c217ff2bd14dcd40a83e319316b2cae3388116234d195bf77bf19abd5422e2e47d80", 1243 | "e0e85917f2c04543a302454a66bca5ce3520c313d6a8c88d6aec7e5720a7552a083c035cca96063dd67af9c4288a9e27c4ee0a519a17adec5ba83234a0bc059c", 1244 | "5631d064b0f51bcfbea77eed49961776f13ca8e0ef42795ad66fc6928c59b25975b40fee8fc058a8ddd11152632b0047dcd9d322bd025b03566205bacde57e26", 1245 | "2308c94619f0cfb0cbe1023f117b39eecbdc00ab4a5d6bc45bde5790b24760afb7962714db71b82539ffe35438419bac0a47daeb12adf4bde061503a080f4786", 1246 | "5d25cd6f9cfd479e806d14012c139ee3f10cb671d909be5b0b17ba95669b298bda865fb343930a694d1010cfeefd07cd3a20f84ed376640a3f77bba77d95bce0", 1247 | "4fa2d31d30a1e2ccb964833be9e7ef678597bebb199a76d99af4d8388a6297d7b77a9e110fceaf8d38c293db9c11ee24912bcef45f947690cf7b1c25aa5bc5f4", 1248 | "0902efb9bb8ba40318beb87fe61a43aab979ccd55bfab832645d9f694527ba47df9c993860fa52a91315827632b42149911e7e5e5d1d927ce071880a10de2d83" 1249 | }; 1250 | 1251 | static vector const thirtytwo_expected = { 1252 | "c238de32a98915279c67528e48e18a96d2fffd7cf889e22ca9054cbcf5d47573", 1253 | "1d28e738c30bca86842d914443590411f32eedd6e21abb0d35c78b570d340396", 1254 | "8bd6726d9a5a9e43b477bc0de67d3d72269dada45385487f2654db94d30714d6", 1255 | "08e2ce62b2949983c8be8e93b01786cbc96ba57cd2c2c1edb4b087c9cfb2f41f", 1256 | "a3190d6ede39a5d157e71881b02ead3e9780b35b0d9effdaf8cc591d29698030", 1257 | "da852b5c560592902bf9a415f57c592ef1464cba02749b2bd0a5f1bff5fb0534", 1258 | "0048b940c000685737a2b6c951680f2afc712d8da11669a741f33692154e373d", 1259 | "60a9b6752eeeee83801d398a95c1509b1dbb8d058cb772614f0bc217f4942590", 1260 | "17c8116db267a04a2bce6462ad8ecabe519686f1b6ad16a5b4554dfde780b609", 1261 | "8fa5343466f7796341d97ff3108eb979858b97fbac73d9bc251257e71854b31f" 1262 | }; 1263 | 1264 | bool success = true; 1265 | #if 0 // don't do anything yet 1266 | for (size_t i = 0; i < sixtyfour_results.size(); i++) 1267 | { 1268 | if (string(*sixtyfour_results[i]) != sixtyfour_expected[i]) 1269 | { 1270 | cerr << "sha3_512 tests failed" << endl; 1271 | success = false; 1272 | break; 1273 | } 1274 | } 1275 | 1276 | for (size_t i = 0; i < thirtytwo_results.size(); i++) 1277 | { 1278 | if (string(*thirtytwo_results[i]) != thirtytwo_expected[i]) 1279 | { 1280 | cerr << "sha3_256 tests failed" << endl; 1281 | success = false; 1282 | break; 1283 | } 1284 | } 1285 | 1286 | cout << "hash is " << std::string(*sixtyfour_results[0]) << endl; 1287 | auto h = sixtyfour_results[0]->deserialize(); 1288 | cout << "deserialized is "; 1289 | for (auto i = h.begin(), iEnd = h.end(); i != iEnd; i++) 1290 | { 1291 | cout << ::std::hex << ::std::setw(2) << ::std::setfill('0') << *i; 1292 | } 1293 | cout << endl; 1294 | 1295 | cout << "encode_int(41) == " << encode_int(41) << endl; 1296 | vector v = {0x41, 0x42}; 1297 | cout << "serialize_hash({41, 42}) == " << sha3_512_t::serialize(v) << endl; 1298 | if (success) 1299 | { 1300 | cout << dec << "all tests passed" << endl; 1301 | } 1302 | #endif 1303 | 1304 | auto progress = [](::std::size_t step, ::std::size_t max, int phase) -> bool 1305 | { 1306 | switch(phase) 1307 | { 1308 | case cache_seeding: 1309 | cout << "\rSeeding cache..."; 1310 | break; 1311 | case cache_generation: 1312 | cout << "\rGenerating cache..."; 1313 | break; 1314 | case cache_saving: 1315 | cout << "\rSaving cache..."; 1316 | break; 1317 | case cache_loading: 1318 | cout << "\rLoading cache..."; 1319 | break; 1320 | case dag_generation: 1321 | cout << "\rGenerating DAG..."; 1322 | break; 1323 | case dag_saving: 1324 | cout << "\rSaving DAG..."; 1325 | break; 1326 | case dag_loading: 1327 | cout << "\rLoading DAG..."; 1328 | break; 1329 | default: 1330 | break; 1331 | } 1332 | cout << fixed << setprecision(2) 1333 | << static_cast(step) / static_cast(max) * 100.0 << "%" 1334 | << setfill(' ') << setw(80) << flush; 1335 | 1336 | return true; 1337 | }; 1338 | 1339 | try 1340 | { 1341 | dag_t loaded("epoch0_generated.dag", progress); 1342 | cout << endl << "\runloading DAG: " << endl; 1343 | loaded.unload(); 1344 | } 1345 | catch (hash_exception const & e) 1346 | { 1347 | cout << endl << "[Exception]: (don't worry about this if you don't have epoch0_generated.dag): " << e.what() << endl; 1348 | } 1349 | 1350 | { 1351 | dag_t generated(0, progress); // generate a DAG 1352 | cout << endl; 1353 | generated.save("epoch0_generated.dag", progress); 1354 | cout << endl; 1355 | } 1356 | 1357 | // clear the global dag cache 1358 | get_dag_cache().clear(); 1359 | 1360 | { 1361 | dag_t loaded("epoch0_generated.dag", progress); 1362 | cout << endl; 1363 | loaded.save("epoch0_loaded.dag", progress); 1364 | cout << endl; 1365 | } 1366 | 1367 | 1368 | //dag_t d("epoch0_verified.dag", progress); 1369 | ////cout << endl << "Saving DAG..." << endl; 1370 | //cout << endl; 1371 | //d.save("epoch0.dag", progress); 1372 | //cout << endl; 1373 | 1374 | return success; 1375 | } 1376 | 1377 | bool test_function() noexcept 1378 | { 1379 | using namespace std; 1380 | bool result = false; 1381 | try 1382 | { 1383 | result = test_function_(); 1384 | } 1385 | catch (::std::exception const & e) 1386 | { 1387 | cerr << "[ERROR]: Caught exception: " << e.what() << endl; 1388 | result = false; 1389 | } 1390 | catch(...) 1391 | { 1392 | cerr << "[ERROR]: Unknown exception." << endl; 1393 | result = false; 1394 | } 1395 | 1396 | return result; 1397 | } 1398 | } 1399 | --------------------------------------------------------------------------------