Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@
[submodule "libraries/libfc/libraries/boringssl/bssl"]
path = libraries/libfc/libraries/boringssl/bssl
url = https://boringssl.googlesource.com/boringssl
[submodule "libraries/libfc/libraries/xxhash/xxHash"]
path = libraries/libfc/libraries/xxhash/xxHash
url = https://github.com/Cyan4973/xxHash
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ configure_file(libraries/prometheus/prometheus-cpp/LICENSE licen
configure_file(programs/cleos/LICENSE.CLI11 licenses/spring/LICENSE.CLI11 COPYONLY)
configure_file(libraries/libfc/libraries/bls12-381/LICENSE licenses/spring/LICENSE.bls12-381 COPYONLY)
configure_file(libraries/libfc/libraries/boringssl/bssl/LICENSE licenses/spring/LICENSE.boringssl COPYONLY)
configure_file(libraries/libfc/libraries/xxhash/xxHash/LICENSE licenses/spring/LICENSE.xxHash COPYONLY)

install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/licenses/spring" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/" COMPONENT base)

Expand Down
2 changes: 2 additions & 0 deletions CMakeModules/EosioTester.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ endif ( APPLE )

add_compile_definitions(BOOST_TEST_DEFAULTS_TO_CORE_DUMP)
add_compile_definitions(BOOST_UNORDERED_DISABLE_NEON)
add_compile_definitions(XXH_INLINE_ALL=1)

set( Boost_USE_MULTITHREADED ON )
set( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
Expand Down Expand Up @@ -118,6 +119,7 @@ target_include_directories(EosioChain INTERFACE
@CMAKE_INSTALL_FULL_INCLUDEDIR@
@CMAKE_INSTALL_FULL_INCLUDEDIR@/wasm-jit
@CMAKE_INSTALL_FULL_INCLUDEDIR@/springboringssl
@CMAKE_INSTALL_FULL_INCLUDEDIR@/springxxhash
@CMAKE_INSTALL_FULL_INCLUDEDIR@/softfloat )

#adds -lrt and -latomic. Ubuntu eosio.contracts build breaks without this
Expand Down
2 changes: 2 additions & 0 deletions CMakeModules/EosioTesterBuild.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ endif ( APPLE )

add_compile_definitions(BOOST_TEST_DEFAULTS_TO_CORE_DUMP)
add_compile_definitions(BOOST_UNORDERED_DISABLE_NEON)
add_compile_definitions(XXH_INLINE_ALL=1)

set( Boost_USE_MULTITHREADED ON )
set( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
Expand Down Expand Up @@ -116,6 +117,7 @@ target_include_directories(EosioChain INTERFACE
@CMAKE_SOURCE_DIR@/libraries/libfc/include
@CMAKE_SOURCE_DIR@/libraries/libfc/libraries/boringssl/bssl/include
@CMAKE_SOURCE_DIR@/libraries/libfc/libraries/bls12-381/include
@CMAKE_SOURCE_DIR@/libraries/libfc/libraries/xxhash
@CMAKE_SOURCE_DIR@/libraries/softfloat/source/include
@CMAKE_SOURCE_DIR@/libraries/appbase/include
@CMAKE_SOURCE_DIR@/libraries/chaindb/include
Expand Down
32 changes: 31 additions & 1 deletion benchmark/hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/crypto/xxh3.hpp>
#include <fc/utility.hpp>

#include <benchmark.hpp>
Expand All @@ -13,7 +14,11 @@ using namespace fc;
namespace eosio::benchmark {

void hash_benchmarking() {
std::string small_message = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ01";
const std::string really_small_message = "abcdefghijklmnop";
const std::string small_message = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ01";

std::span<const char, 16> really_small_message_span(really_small_message.data(), 16);
std::span<const char, 64> small_message_span(small_message.data(), 64);

// build a large message
constexpr auto large_msg_size = 4096;
Expand Down Expand Up @@ -84,6 +89,31 @@ void hash_benchmarking() {
};
benchmarking("keccak256 (" + std::to_string(large_message.length()) + " bytes)", keccak_large_msg);

auto xxh3_really_small_message = [&]() {
fc::xxh3::hash(really_small_message);
};
benchmarking("xxh3 (" + std::to_string(really_small_message.length()) + " bytes)", xxh3_really_small_message);

auto xxh3_small_msg = [&]() {
fc::xxh3::hash(small_message);
};
benchmarking("xxh3 (" + std::to_string(small_message.length()) + " bytes)", xxh3_small_msg);

auto xxh3_large_msg = [&]() {
fc::xxh3::hash(large_message);
};
benchmarking("xxh3 (" + std::to_string(large_message.length()) + " bytes)", xxh3_large_msg);

auto xxh3_really_small_fixed_message = [&]() {
fc::xxh3::hash_raw(really_small_message_span);
};
benchmarking("xxh3 fixed (" + std::to_string(really_small_message_span.size()) + " bytes)", xxh3_really_small_fixed_message);

auto xxh3_small_fixed_msg = [&]() {
fc::xxh3::hash_raw(small_message_span);
};
benchmarking("xxh3 fixed (" + std::to_string(small_message_span.size()) + " bytes)", xxh3_small_fixed_msg);

}

} // benchmark
4 changes: 3 additions & 1 deletion libraries/libfc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ add_subdirectory( secp256k1 )
add_subdirectory( libraries/bn256/src )
add_subdirectory( libraries/bls12-381 )
add_subdirectory( libraries/boringssl )
add_subdirectory( libraries/xxhash )

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
Expand Down Expand Up @@ -59,6 +60,7 @@ set( fc_sources
src/crypto/modular_arithmetic.cpp
src/crypto/blake2.cpp
src/crypto/k1_recover.cpp
src/crypto/xxh3.cpp
src/network/url.cpp
src/network/http/http_client.cpp
src/compress/zlib.cpp
Expand Down Expand Up @@ -105,7 +107,7 @@ endif()

target_link_libraries( fc PUBLIC Boost::date_time Boost::chrono Boost::iostreams Boost::interprocess Boost::multi_index Boost::dll
Boost::multiprecision Boost::beast Boost::asio Boost::thread Boost::crc Threads::Threads
boringssl ZLIB::ZLIB ${PLATFORM_SPECIFIC_LIBS} ${CMAKE_DL_LIBS} secp256k1 bls12-381
boringssl ZLIB::ZLIB ${PLATFORM_SPECIFIC_LIBS} ${CMAKE_DL_LIBS} secp256k1 bls12-381 xxhash
${security_framework} ${corefoundation_framework})

add_subdirectory( test )
Expand Down
62 changes: 62 additions & 0 deletions libraries/libfc/include/fc/crypto/xxh3.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#pragma once

#include <fc/fwd.hpp>
#include <fc/crypto/packhash.hpp>
#include <fc/io/raw_fwd.hpp>

#include <xxHash/xxhash.h>

namespace fc {

namespace detail {
struct alignas(64) alignmeto64 {};

template <typename T>
concept ContiguousCharSource = requires(const T& obj) {
{ obj.data() } -> std::convertible_to<const char*>;
{ obj.size() } -> std::unsigned_integral;
};
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really need a better place for stuff like this -- even just putting in detail here doesn't protect against against ODR oopsies since it's just in fc::detail still.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put in a separate file with a different name space?


struct xxh3 : public add_packhash_to_hash<xxh3> {
xxh3() = default;
explicit xxh3(const uint64_t h) : _hash(h) {}

///no data() since would that be confusing LE/BE? but that breaks common interface across hash types
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like how the hash interface is a little different for xxh3 vs other hash types (well, the sha3 one is different too). They really all should conform to an identical interface. This comment explains my hesitancy to put in data(), but the reason for the hash_raw() (that may remember from some earlier PRs like #1719!) is that the single-shot fixed-length hash tends to be about 25% faster in my tests, so I really want that.


static xxh3 hash(const char* d, uint32_t dlen);
static xxh3 hash(const std::string&);

template<typename T>
static xxh3 hash( const T& t ) {
return packhash(t);
}

static xxh3 hash_raw(const detail::ContiguousCharSource auto& r) {
return xxh3{XXH3_64bits(r.data(), r.size())};
}

class encoder {
public:
encoder();

void write( const char* d, uint32_t dlen );
void put( char c ) { write( &c, 1 ); }
void reset();
xxh3 result();

private:
struct impl;
//XXH3_state_t documents requirement of 64 byte alignment.
fc::fwd<impl,576,detail::alignmeto64> my;
};

friend auto operator<=>(const xxh3&, const xxh3&) = default;

uint64_t _hash = 0;
};

}

FC_REFLECT(xxh3, (_hash))

5 changes: 5 additions & 0 deletions libraries/libfc/libraries/xxhash/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
add_library(xxhash INTERFACE)
target_include_directories(xxhash INTERFACE .)
target_compile_definitions(xxhash INTERFACE -DXXH_INLINE_ALL=1)

install(FILES xxHash/xxhash.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/springxxhash/xxHash" COMPONENT dev EXCLUDE_FROM_ALL)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library is used header only now; fwiw in an earlier revision I was compiling it as a library and this allows me to access the "x86dispatch" optimizations,
https://github.com/AntelopeIO/spring/blob/c8edec420f4121ca665ceb3d506608c09f81203f/libraries/libfc/libraries/xxhash/CMakeLists.txt
I might explore that again some time, but the current single-shot performance is around 15ns on my box which is plenty fast enough for our event use case I believe.

1 change: 1 addition & 0 deletions libraries/libfc/libraries/xxhash/xxHash
Submodule xxHash added at e626a7
34 changes: 34 additions & 0 deletions libraries/libfc/src/crypto/xxh3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <fc/crypto/xxh3.hpp>
#include <fc/fwd_impl.hpp>

namespace fc {

struct xxh3::encoder::impl {
XXH3_state_t ctx;
};

xxh3::encoder::encoder() {
reset();
}
void xxh3::encoder::reset() {
XXH3_64bits_reset(&my->ctx);
}
void xxh3::encoder::write(const char* d, uint32_t dlen) {
XXH3_64bits_update(&my->ctx, d, dlen);
}
xxh3 xxh3::encoder::result() {
xxh3 h;
h._hash = XXH3_64bits_digest(&my->ctx);
return h;
}

xxh3 xxh3::hash(const char* d, uint32_t dlen) {
encoder e;
e.write(d,dlen);
return e.result();
}
xxh3 xxh3::hash(const std::string& s) {
return hash(s.data(), s.size());
}

}
33 changes: 33 additions & 0 deletions libraries/libfc/test/crypto/test_hash_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

#include <fc/crypto/hex.hpp>
#include <fc/crypto/sha3.hpp>
#include <fc/crypto/xxh3.hpp>
#include <fc/utility.hpp>

#include <span>

using namespace fc;

BOOST_AUTO_TEST_SUITE(hash_functions)
Expand Down Expand Up @@ -66,4 +69,34 @@ BOOST_AUTO_TEST_CASE(keccak256) try {

} FC_LOG_AND_RETHROW();

#define XSUM_U8 uint8_t
#define XSUM_U32 uint32_t
#define XSUM_U64 uint64_t
typedef struct {
uint64_t low64;
uint64_t high64;
} XXH128_hash_t;
#include <xxHash/tests/sanity_test_vectors.h>

BOOST_AUTO_TEST_CASE(xhh3) try {
//reconstruct test vector input from xxhash library's tests
char sanity_buffer[4096+64+1];

uint64_t byte_gen = 2654435761U;
for(unsigned i = 0; i < sizeof(sanity_buffer); ++i) {
sanity_buffer[i] = (char)(byte_gen>>56);
byte_gen *= 11400714785074694797ULL;
}

for(const XSUM_testdata64_t& t : XSUM_XXH3_testdata) {
//non-zero seed not exposed by fc's xxh3 interface
if(t.seed != 0)
continue;

BOOST_CHECK_EQUAL(t.Nresult, xxh3::hash(sanity_buffer, t.len)._hash);
BOOST_CHECK_EQUAL(t.Nresult, xxh3::hash_raw(std::span(sanity_buffer, t.len))._hash);
}

} FC_LOG_AND_RETHROW();

BOOST_AUTO_TEST_SUITE_END()