diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/.vscode/settings.json" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/.vscode/settings.json"
new file mode 100644
index 0000000000000000000000000000000000000000..0d951ad8cb03f4f685c3434f0f62c5473bad6cb3
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/.vscode/settings.json"
@@ -0,0 +1,47 @@
+{
+ "files.associations": {
+ "iostream": "cpp",
+ "any": "cpp",
+ "array": "cpp",
+ "atomic": "cpp",
+ "*.tcc": "cpp",
+ "cctype": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "cstdarg": "cpp",
+ "cstddef": "cpp",
+ "cstdint": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "cwchar": "cpp",
+ "cwctype": "cpp",
+ "deque": "cpp",
+ "list": "cpp",
+ "unordered_map": "cpp",
+ "vector": "cpp",
+ "exception": "cpp",
+ "algorithm": "cpp",
+ "memory": "cpp",
+ "memory_resource": "cpp",
+ "optional": "cpp",
+ "string": "cpp",
+ "string_view": "cpp",
+ "system_error": "cpp",
+ "tuple": "cpp",
+ "type_traits": "cpp",
+ "utility": "cpp",
+ "fstream": "cpp",
+ "initializer_list": "cpp",
+ "iosfwd": "cpp",
+ "istream": "cpp",
+ "limits": "cpp",
+ "new": "cpp",
+ "ostream": "cpp",
+ "sstream": "cpp",
+ "stdexcept": "cpp",
+ "streambuf": "cpp",
+ "typeinfo": "cpp",
+ "variant": "cpp"
+ }
+}
\ No newline at end of file
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/CMakeLists.txt" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/CMakeLists.txt"
new file mode 100644
index 0000000000000000000000000000000000000000..a6b70542cc85563d5a6d9b89cc1ada7ddca0fa3e
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/CMakeLists.txt"
@@ -0,0 +1,44 @@
+# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+# secGear is licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+
+project(hope CXX)
+
+# set(CMAKE_C_STANDARD 99)
+set(CMAKE_CXX_STANDARD 17)
+
+
+set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+
+#set edl name
+set(EDL_FILE hope.edl)
+set(CODEGEN codegen)
+
+if(CC_GP)
+ set(CODETYPE trustzone)
+ set(UUID f68fd704-6eb1-4d14-b218-722850eb3ef0)
+ add_definitions(-DPATH="/data/${UUID}.sec")
+endif()
+
+if (NOT DEFINED SSL_PATH)
+ set(SSL_PATH /opt/intel/sgxssl)
+endif()
+
+if(CC_SGX)
+ set(CODETYPE sgx)
+ add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so")
+endif()
+
+if(CC_PL)
+ set(CODETYPE penglai)
+ add_definitions(-DPATH="${CMAKE_CURRENT_SOURCE_DIR}/enclave/penglai-ELF")
+endif()
+
+add_subdirectory(${CURRENT_ROOT_PATH}/enclave)
+add_subdirectory(${CURRENT_ROOT_PATH}/host)
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/CMakeLists.txt" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/CMakeLists.txt"
new file mode 100644
index 0000000000000000000000000000000000000000..bd64c2203be5bf444f3a17c32a83adb414a2696c
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/CMakeLists.txt"
@@ -0,0 +1,234 @@
+# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+# secGear is licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+
+#set auto code prefix
+set(PREFIX hope)
+
+#set sign key
+set(PEM Enclave_private.pem)
+
+#set sign tool
+set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh)
+
+#set enclave src code
+set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/hope.cpp)
+
+#set log level
+set(PRINT_LEVEL 3)
+add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL})
+
+if(CC_GP)
+ #set signed output
+ set(OUTPUT ${UUID}.sec)
+ #set whilelist. default: /vendor/bin/teec_hello
+ set(WHITE_LIST_0 /vendor/bin/helloworld)
+ set(WHITE_LIST_OWNER root)
+ set(WHITE_LIST_1 /vendor/bin/secgear_helloworld)
+ set(WHITELIST WHITE_LIST_0 WHITE_LIST_1)
+
+ set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h)
+ add_custom_command(OUTPUT ${AUTO_FILES}
+ DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp)
+endif()
+
+if(CC_SGX)
+ set(OUTPUT enclave.signed.so)
+ set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c)
+ add_custom_command(OUTPUT ${AUTO_FILES}
+ DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SDK_PATH}/include --search-path ${SSL_PATH}/include)
+endif()
+
+if(CC_PL)
+ set(OUTPUT penglai-ELF)
+ set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h)
+ add_custom_command(OUTPUT ${AUTO_FILES}
+ DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/penglai)
+endif()
+
+set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer -fstack-protector \
+ -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \
+ -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \
+ -Wno-error=unused-but-set-variable -Wno-error=format-truncation=")
+
+set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles")
+
+if(CC_GP)
+
+ set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC")
+ set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s")
+
+ set(ITRUSTEE_TEEDIR ${SDK_PATH}/)
+ set(ITRUSTEE_LIBC ${SDK_PATH}/thirdparty/open_source/musl/libc)
+
+ if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(${CMAKE_BINARY_DIR}/lib/)
+ endif()
+
+ add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES})
+
+ target_include_directories( ${PREFIX} PRIVATE
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc/gp
+ ${LOCAL_ROOT_PATH}/inc/enclave_inc
+ ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp
+ ${ITRUSTEE_TEEDIR}/include/TA
+ ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext
+ ${ITRUSTEE_LIBC}/arch/aarch64
+ ${ITRUSTEE_LIBC}/
+ ${ITRUSTEE_LIBC}/arch/arm/bits
+ ${ITRUSTEE_LIBC}/arch/generic
+ ${ITRUSTEE_LIBC}/arch/arm
+ ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee)
+
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${PREFIX} PRIVATE
+ ${CMAKE_BINARY_DIR}/lib/)
+ endif()
+
+ foreach(WHITE_LIST ${WHITELIST})
+ add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}")
+ endforeach(WHITE_LIST)
+ add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}")
+
+ target_link_libraries(${PREFIX} -lsecgear_tee)
+
+ #for trustzone compiling, you should connact us to get config and private_key.pem for test, so we will not sign and install binary in this example #
+ # add_custom_command(TARGET ${PREFIX}
+ # POST_BUILD
+ # COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini -o ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT})
+
+ # install(FILES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT}
+ # DESTINATION /data
+ # PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+
+endif()
+
+if(CC_SGX)
+ set(SGX_DIR ${SDK_PATH})
+ set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s")
+ set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64)
+
+ set(OPENSSL_LIBRARY_PATH ${SSL_PATH}/lib64) # openssl动态库
+
+ if(CC_SIM)
+ set(Trts_Library_Name sgx_trts_sim)
+ set(Service_Library_Name sgx_tservice_sim)
+ else()
+ set(Trts_Library_Name sgx_trts)
+ set(Service_Library_Name sgx_tservice)
+ endif()
+
+ set(Crypto_Library_Name sgx_tcrypto)
+
+ set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \
+ -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds")
+
+ if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(
+ ${LINK_LIBRARY_PATH}
+ ${OPENSSL_LIBRARY_PATH}
+ )
+ endif()
+
+ add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES})
+
+ target_include_directories(${PREFIX} PRIVATE
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${SGX_DIR}/include/tlibc
+ ${SGX_DIR}/include/libcxx
+ ${SGX_DIR}/include
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc/sgx
+ ${SSL_PATH}/include #openssl静态库
+ ${CURRENT_ROOT_PATH}/include
+ )
+
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${PREFIX} PRIVATE
+ ${LINK_LIBRARY_PATH}
+ ${OPENSSL_LIBRARY_PATH}
+ ${CURRENT_ROOT_PATH}/include
+ )
+ endif()
+
+ target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -lsgx_tsgxssl -Wl,--no-whole-archive
+ -Wl,--start-group
+ -lsgx_tstdc -lsgx_tcxx -lsgx_tsgxssl -lsgx_tsgxssl_crypto -lsgx_usgxssl
+ -lsgx_tcrypto -lsgx_pthread
+ -l${Crypto_Library_Name} -l${Service_Library_Name}
+ -Wl,--end-group)
+ add_custom_command(TARGET ${PREFIX}
+ POST_BUILD
+ COMMAND umask 0177
+ COMMAND openssl genrsa -3 -out ${PEM} 3072
+ COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml)
+endif()
+
+if(NOT DEFINED CC_PL)
+ set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE)
+endif()
+
+if(CC_PL)
+ set(SDK_LIB_DIR ${SDK_PATH}/lib)
+ set(SDK_INCLUDE_DIR ${SDK_LIB_DIR}/app/include)
+ set(SDK_APP_LIB ${SDK_LIB_DIR}/libpenglai-enclave-eapp.a)
+ set(MUSL_LIB_DIR ${SDK_PATH}/musl/lib)
+ set(MUSL_LIBC ${MUSL_LIB_DIR}/libc.a)
+ set(GCC_LIB ${SDK_LIB_DIR}/libgcc.a)
+ set(SECGEAR_TEE_LIB ${CMAKE_BINARY_DIR}/lib/libsecgear_tee.a)
+
+ set(SOURCE_C_OBJS "")
+ foreach(SOURCE_FILE ${SOURCE_FILES})
+ STRING(REGEX REPLACE ".+/(.+)\\..*" "\\1" SOURCE_FILE_NAME ${SOURCE_FILE})
+ set(SOURCE_OBJ ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_FILE_NAME}.o)
+ add_custom_command(
+ OUTPUT ${SOURCE_OBJ}
+ DEPENDS ${SOURCE_FILES}
+ COMMAND gcc -Wall -I${SDK_INCLUDE_DIR} -I${CMAKE_CURRENT_BINARY_DIR} -I${CMAKE_BINARY_DIR}/inc
+ -I${LOCAL_ROOT_PATH}/inc/host_inc -I${LOCAL_ROOT_PATH}/inc/host_inc/penglai -I${LOCAL_ROOT_PATH}/inc/enclave_inc
+ -I${LOCAL_ROOT_PATH}/inc/enclave_inc/penglai -c -o ${SOURCE_OBJ} ${SOURCE_FILE}
+ COMMENT "generate SOURCE_OBJ"
+ )
+ list(APPEND SOURCE_C_OBJS ${SOURCE_OBJ})
+ endforeach()
+
+ set(APP_C_OBJ ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.o)
+ add_custom_command(
+ OUTPUT ${APP_C_OBJ}
+ DEPENDS ${AUTO_FILES}
+ COMMAND gcc -Wall -I${SDK_INCLUDE_DIR} -I${CMAKE_CURRENT_BINARY_DIR} -I${CMAKE_BINARY_DIR}/inc
+ -I${LOCAL_ROOT_PATH}/inc/host_inc -I${LOCAL_ROOT_PATH}/inc/host_inc/penglai -I${LOCAL_ROOT_PATH}/inc/enclave_inc
+ -I${LOCAL_ROOT_PATH}/inc/enclave_inc/penglai -c -o ${APP_C_OBJ} ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c
+ COMMENT "generate APP_C_OBJ"
+ )
+
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT}
+ DEPENDS ${APP_C_OBJ} ${SOURCE_C_OBJS} ${SDK_APP_LIB} ${MUSL_LIBC} ${GCC_LIB}
+ COMMAND ld -static -L${SDK_LIB_DIR} -L${MUSL_LIB_DIR} -L/usr/lib64 -lpenglai-enclave-eapp -lsecgear_tee -lc
+ -o ${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT} ${APP_C_OBJ} ${SOURCE_C_OBJS} ${SDK_APP_LIB} ${SECGEAR_TEE_LIB}
+ ${MUSL_LIBC} ${GCC_LIB} -T ${SDK_PATH}/app.lds
+ COMMAND chmod -x ${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT}
+ COMMENT "generate penglai-ELF"
+ )
+ add_custom_target(
+ ${OUTPUT} ALL
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT}
+ COMMENT "makefile target penglai-ELF"
+ )
+
+endif()
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/Enclave.config.xml" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/Enclave.config.xml"
new file mode 100644
index 0000000000000000000000000000000000000000..bd60be70ea40d3d06384de5ac747909597fef4c4
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/Enclave.config.xml"
@@ -0,0 +1,12 @@
+
+ 0
+ 0
+ 0x400000
+ 0x100000000
+ 10
+ 1
+
+ 0
+ 0
+ 0xFFFFFFFF
+
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/Enclave.lds" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/Enclave.lds"
new file mode 100644
index 0000000000000000000000000000000000000000..ab77e6478ef3c3448356e80b9884a8a533dd32c6
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/Enclave.lds"
@@ -0,0 +1,11 @@
+enclave.so
+{
+ global:
+ g_global_data_sim;
+ g_global_data;
+ enclave_entry;
+ g_peak_heap_used;
+ local:
+ *;
+};
+
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/config_cloud.ini" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/config_cloud.ini"
new file mode 100644
index 0000000000000000000000000000000000000000..8c70225ecd3f2e7de449e89cbe338b81e1f06db9
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/config_cloud.ini"
@@ -0,0 +1,60 @@
+[signSecPrivateCfg]
+;;;
+;private key length for signing TA:
+;[fixed value]
+;256 ECDSA Alg
+;2048/4096 RSA Alg
+secSignKeyLen = 4096
+;;;
+;[fixed value]
+;0 means SHA256 hash type
+;1 means SHA512 hash type
+secHashType = 0
+;;;
+; [fixed value]
+;0 means padding type is pkcs1v15
+;1 means padding type is PSS
+;[fixed value]
+secPaddingType = 1
+;;;
+;[fixed value]
+;RSA alg
+;ECDSA alg
+;SM2 alg
+secSignAlg = RSA
+;;;
+;public key for encrypt TA
+secEncryptKey = rsa_public_key_cloud.pem
+;;;
+;public key length
+secEncryptKeyLen = 3072
+
+[signSecPublicCfg]
+;;;
+;[fixed value]
+; sec sign key type
+;0 means debug
+;1 means release
+secReleaseType = 1
+;;;
+;0 means TA not installed by OTRP
+;1 means TA installed by OTRP
+secOtrpFlag = 0
+;;;
+;0 means not sign
+;1 means signed by local private
+;2 means signed using native sign tool;
+;3 means signed by CI
+;[fixed value]
+secSignType = 1
+;;;
+;server address for signing TA
+secSignServerIp =
+;;;
+;private key for signing TA
+;[private key owned by yourself]
+secSignKey = /home/TA_cert/private_key.pem
+;;;
+;config file
+;[signed config file by Huawei]
+configPath = /home/TA_cert/secgear-app1/config
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/hope.cpp" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/hope.cpp"
new file mode 100644
index 0000000000000000000000000000000000000000..080a4265c9cc95f620066256ec2c4fca0a795d0f
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/hope.cpp"
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "common.h"
+#include "robin_hood.h"
+#include "hope_t.h"
+using namespace std;
+
+#define TA_HELLO_WORLD "secgear hello world!"
+#define BUF_MAX 32
+#define NUM_INSTRUCTIONS 200000
+#define KEY_SIZE 16
+#define VALUE_SIZE 16
+#define BUF_SIZE (4+KEY_SIZE+1+VALUE_SIZE+1)
+
+const uint8_t userkey[16] = { // AES密钥生成参数
+ '1', '2', '3', '4',
+ '5', '6', '7', '8',
+ '9', '0', '1', '2',
+ '3', '4', 'b', 'a'
+};
+
+const uint8_t secretKey[16] = {
+ 'e', 'n', 'c', 'l',
+ 'a', 'v', 'e', 's',
+ 'e', 'c', 'r', 'e',
+ 't', 'k', 'e', 'y'
+};
+
+struct Pair {
+ unsigned char enc_val[32];
+ unsigned char iv[16];
+ // uint32_t key_size; key在enclave里明文存储应该这一部分就暂时不需要keysize了
+ uint32_t value_size;
+ unsigned char cmac[16];
+};
+
+// 自定义哈希函数和比较函数
+struct uchar_array_hash {
+ std::size_t operator()(const std::array& key) const noexcept {
+ std::size_t hash = 0;
+ for (auto byte : key) {
+ hash ^= std::hash{}(byte) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
+ }
+ return hash;
+ }
+};
+
+struct uchar_array_equal {
+ bool operator()(const std::array& lhs, const std::array& rhs) const noexcept {
+ return lhs == rhs;
+ }
+};
+
+// 定义 HashTable 类型
+// typedef robin_hood::unordered_map, Pair, uchar_array_hash, uchar_array_equal> HashTable;
+typedef robin_hood::unordered_map, uint64_t, uchar_array_hash, uchar_array_equal> HashTable;
+
+HashTable * root_table = nullptr;
+
+
+void AES_CTR_Encrypt(const unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext, unsigned char *iv){
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER *cipher = nullptr;
+ EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), nullptr,(const unsigned char*)userkey, iv);
+ int ciphertext_len;
+ EVP_EncryptUpdate(ctx, ciphertext, &ciphertext_len, plaintext, plaintext_len);
+ int len;
+ EVP_EncryptFinal_ex(ctx, ciphertext+ciphertext_len, &len);
+ ciphertext_len += len;
+ EVP_CIPHER_CTX_free(ctx);
+ // EVP_CIPHER_CTX_init(ctx);
+}
+
+void AES_CTR_Decrypt(const unsigned char * ciphertext, int ciphertext_len, unsigned char *plaintext, unsigned char *iv){
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_ctr(), nullptr,(const unsigned char*)userkey, iv);
+ int plaintext_len;
+ EVP_DecryptUpdate(ctx, plaintext, &plaintext_len, ciphertext, ciphertext_len);
+ int len;
+ EVP_DecryptFinal_ex(ctx, plaintext+plaintext_len, &len);
+ plaintext_len += len;
+ EVP_CIPHER_CTX_free(ctx);
+}
+
+void Compute_CMAC(const unsigned char * data1, int data1_len, const unsigned char * data2, int data2_len, unsigned char * cmac_result){
+ // print(cmac_result);
+ memset(cmac_result,0,sizeof(cmac_result));
+ CMAC_CTX *ctx = CMAC_CTX_new();
+ CMAC_Init(ctx, userkey, 16, EVP_aes_128_cbc(), nullptr);
+ CMAC_Update(ctx, data1, data1_len);
+ CMAC_Update(ctx, data2, data2_len);
+ size_t cmac_len;
+ CMAC_Final(ctx, cmac_result, &cmac_len);
+ // print(cmac_result);
+ CMAC_CTX_free(ctx);
+}
+
+void initEnclave(){
+ HashTable *key_hash_table = new HashTable();
+ root_table = key_hash_table;
+ if(root_table == nullptr){
+ printstr("init失败");
+ }
+}
+
+
+
+// 因为要先实现第一部分,对于SET来说,就是 需要在enclave里建一个关于key的hashtable,应该包括 key-ptr
+// 先把value加密,之后根据提前分配好的地址 把加密的value 放进去,ptr存到hashtable里,应该也是要存剩下的 valuesize 和 value iv 和 cmac
+void SET_KV_Pair(const char* key, const char* value, uint64_t pair_addr){
+ // 先对传进来的value加密
+ // 一些输入检查
+ char use_key[17];
+ memset(use_key,0,sizeof(use_key));
+ memcpy(use_key, key, 16);
+ use_key[16] = '\0';
+ // pair地址转化过来
+ Pair * pair = (Pair *)pair_addr;
+ // 加密前的准备工作
+ RAND_poll();
+ int value_len = strlen(value);
+ int key_len = strlen(use_key);
+ unsigned char enc_value[32];
+ unsigned char value_iv[16];
+ unsigned char cmac_res[16];
+ RAND_bytes(value_iv,16);
+ // 对value进行加密,计算cmac
+ AES_CTR_Encrypt(reinterpret_cast(value), value_len, enc_value, value_iv);
+ Compute_CMAC(value_iv, 16, enc_value, value_len, cmac_res);
+ // 把加密后的value iv valuesize cmac 存放在非安全区
+ memcpy(pair->enc_val, enc_value, sizeof(pair->enc_val));
+ memcpy(pair->iv, value_iv, sizeof(pair->iv));
+ memcpy(pair->cmac, cmac_res, sizeof(pair->cmac));
+ pair->value_size = value_len;
+ // 存储到hashtable里
+ std::array key_arr = {};
+ memcpy(key_arr.data(), key, key_len);
+ (*root_table)[key_arr] = pair_addr;
+ // print_hash_table((uint64_t)root_table);
+}
+
+
+
+// 那对于get来说就是 根据key 从hash里取出pair的addr,之后验证pair的cmac,然后解密value就好了
+void GET_KV_Pair(const char *key, unsigned char *plain_value){
+ HashTable * table = root_table;
+ // print_hash_table();
+ // 加密key 调用函数
+ int key_len = strlen(key);
+ // printint(key_len);
+ // printstr(key);
+ // 尝试从hash表中找到对应的建
+ std::array key_arr = {};
+ memcpy(key_arr.data(), key, key_len);
+ auto it = table->find(key_arr);
+ if(it != table->end()){
+ // 找到匹配的键
+ uint64_t pair_addr = it->second;
+ Pair * pair = (Pair *)pair_addr;
+ // 解密对应value
+ // print(pair.cmac);
+ // print(pair.enc_val);
+ // 验证cmac 之后补充这部分的代码
+ unsigned char cmac_res[16]={0};
+ memset(cmac_res,0,sizeof(cmac_res));
+ Compute_CMAC(pair->iv, 16, pair->enc_val, pair->value_size, cmac_res);
+ if(memcmp(pair->cmac, cmac_res, 16)==0){
+ AES_CTR_Decrypt(pair->enc_val, pair->value_size, plain_value, pair->iv);
+ // print(plain_value);
+ }
+ else{
+ printstr("cmac验证失败");
+ }
+ }
+ else{
+ printstr("GET FIELD!!!");
+ }
+}
+
+void process_workload(uint64_t instructions_addr, uint64_t pair_array_addr){
+ char ***instructions = (char ***)instructions_addr;
+ Pair **pair_array = (Pair **)pair_array_addr;
+ HashTable * table = root_table;
+
+ unsigned char plain_value[33]={};
+
+ size_t j = 0;
+ for(int i = 0; i < NUM_INSTRUCTIONS; i++){
+ if(strcmp(instructions[i][0],"GET") == 0){
+ printstr(instructions[i][1]);
+ GET_KV_Pair(instructions[i][1], plain_value);
+ plain_value[32] = '\0';
+ // print(plain_value);
+ memset(plain_value,0,VALUE_SIZE);
+ }
+ else if(strcmp(instructions[i][0],"SET") == 0){
+ SET_KV_Pair(instructions[i][1],instructions[i][2],(uint64_t)pair_array[j]);
+ j++;
+ }
+ }
+ // printstr("_______________________________");
+}
+
+
+
+
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/manifest.txt" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/manifest.txt"
new file mode 100644
index 0000000000000000000000000000000000000000..d78354e6c0e101a126d65a116c4e98765f852db7
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/enclave/manifest.txt"
@@ -0,0 +1,7 @@
+gpd.ta.appID: f68fd704-6eb1-4d14-b218-722850eb3ef0
+gpd.ta.service_name: rsa-demo
+gpd.ta.singleInstance: true
+gpd.ta.multiSession: false
+gpd.ta.instanceKeepAlive: false
+gpd.ta.dataSize: 819200
+gpd.ta.stackSize: 40960
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/hope.edl" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/hope.edl"
new file mode 100644
index 0000000000000000000000000000000000000000..f8d7dd6ced936f913498c5260f470662000665ee
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/hope.edl"
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+enclave {
+ include "secgear_urts.h"
+ from "secgear_tstdc.edl" import *;
+ from "secgear_tssl.edl" import *;
+ from "secgear_pthread.edl" import*;
+ trusted {
+ // public void AES_ECB_Encrypt([in, size=32]uint8_t *value, [out, size=32]uint8_t *buf);
+ // public void AES_ECB_Decrypt([in, size=32]uint8_t *value, [out, size=32]uint8_t *buf);
+ // public void compute_key_iv([in, size=32]const char *key, [out, size=32]unsigned char *iv_result);
+ // public void test_decrypt_enckey([in, size=32]const char *key, [in, size=32]unsigned char *encKey, int key_size, [out, size=32]unsigned char *plaintext);
+ // public void Encrypt_Key_For_Find([in, size=32]const char *key, [out, size=32]unsigned char *cipherKey);
+ public void initEnclave();
+ public void SET_KV_Pair([in, size=32]const char* key, [in, size=32]const char* value, uint64_t pair_addr);
+ public void GET_KV_Pair([in, size=32]const char *key, [out, size=32]unsigned char *plain_value);
+ public void process_workload(uint64_t instructions_addr, uint64_t pair_array_addr);
+ // public void AES_CTR_Encrypt([in, size=32]const unsigned char *plaintext, int plaintext_len, [out, size=32]unsigned char *ciphertext, [in, size=16]unsigned char *iv);
+ // public void AES_CTR_Decrypt([in, size=32]const unsigned char * ciphertext, int ciphertext_len, [out, size=32]unsigned char *plaintext, [in, size=16]unsigned char *iv);
+ // public void Compute_CMAC([in, size=32]const unsigned char * data1, int data1_len, [in, size=32]const unsigned char * data2, int data2_len, [out, size=32]unsigned char * cmac_result);
+ };
+ untrusted {
+ void print([in, size=64]unsigned char* iv_test);
+ void printstr([in, size=64]char* str);
+ void print1(uint64_t addr);
+ void print_hash_table(uint64_t table_addr);
+ void printint(int a);
+ void pirnt_inst(uint64_t a);
+ };
+};
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/host/CMakeLists.txt" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/host/CMakeLists.txt"
new file mode 100644
index 0000000000000000000000000000000000000000..20693294605453bacaf745a47a8ca0e53acee83c
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/host/CMakeLists.txt"
@@ -0,0 +1,130 @@
+# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+# secGear is licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+
+#set auto code prefix
+set(PREFIX hope)
+#set host exec name
+set(OUTPUT secgear_hope)
+#set host src code
+set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
+
+#set auto code
+if(CC_GP)
+ set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h)
+ add_custom_command(OUTPUT ${AUTO_FILES}
+ DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp)
+endif()
+
+if(CC_SGX)
+ set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c)
+ add_custom_command(OUTPUT ${AUTO_FILES}
+ DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx
+ --search-path ${SDK_PATH}/include
+ --search-path ${SSL_PATH}/include)
+endif()
+
+if(CC_PL)
+ set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c)
+ add_custom_command(OUTPUT ${AUTO_FILES}
+ DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
+ COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/penglai)
+endif()
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
+set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s")
+
+if(CC_GP)
+ if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+ endif()
+ add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES})
+ target_include_directories(${OUTPUT} PRIVATE
+ ${CMAKE_BINARY_DIR}/inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc/gp
+ ${CMAKE_CURRENT_BINARY_DIR})
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+ endif()
+endif()
+
+if(CC_SGX)
+ if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
+ ${SSL_PATH}/lib64
+ )
+ endif()
+ add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES})
+ target_include_directories(${OUTPUT} PRIVATE
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc/sgx
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CURRENT_ROOT_PATH}/include/)
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${OUTPUT} PRIVATE
+ ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
+ ${SSL_PATH}/lib64
+ ${CURRENT_ROOT_PATH}/include/
+ )
+ endif()
+endif()
+
+if(CC_PL)
+ if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+ endif()
+ add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES})
+ target_include_directories(${OUTPUT} PRIVATE
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${LOCAL_ROOT_PATH}/inc/host_inc/penglai
+ ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+ endif()
+endif()
+
+if(CC_SIM)
+ target_link_libraries(${OUTPUT} secgearsim pthread sgx_usgxssl) # 链接动态库
+else()
+ target_link_libraries(${OUTPUT} secgear pthread sgx_usgxssl)
+endif()
+set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE)
+
+if(CC_GP)
+ #itrustee install whitelist /vender/bin/teec_hello
+ install(TARGETS ${OUTPUT}
+ RUNTIME
+ DESTINATION /vendor/bin/
+ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
+ GROUP_EXECUTE GROUP_READ
+ WORLD_EXECUTE WORLD_READ)
+endif()
+
+if(CC_SGX)
+ install(TARGETS ${OUTPUT}
+ RUNTIME
+ DESTINATION ${CMAKE_BINARY_DIR}/bin/
+ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
+ GROUP_EXECUTE GROUP_READ
+ WORLD_EXECUTE WORLD_READ)
+endif()
+
+if(CC_PL)
+ install(TARGETS ${OUTPUT}
+ RUNTIME
+ DESTINATION ${CMAKE_BINARY_DIR}/bin/
+ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
+ GROUP_EXECUTE GROUP_READ
+ WORLD_EXECUTE WORLD_READ)
+endif()
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/host/main.cpp" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/host/main.cpp"
new file mode 100644
index 0000000000000000000000000000000000000000..ea6ed3fc011a47a7ca58b10ac22782c8b846060f
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/host/main.cpp"
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#include
+#include
+#include
+#include "enclave.h"
+#include "hope_u.h"
+#include "string.h"
+#include "robin_hood.h"
+
+#include
+#include
+#include // 使用高精度计时器
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define BUF_LEN 32
+#define NUM_INSTRUCTIONS 200000
+#define KEY_SIZE 16
+#define VALUE_SIZE 16
+#define BUF_SIZE (4+KEY_SIZE+1+VALUE_SIZE+1)
+
+// Pair 结构体,用于存储值部分
+struct Pair {
+ unsigned char enc_val[32];
+ unsigned char iv[16];
+ uint32_t key_size;
+ uint32_t value_size;
+ unsigned char cmac[16];
+};
+
+// 自定义哈希函数和比较函数
+struct uchar_array_hash {
+ std::size_t operator()(const std::array& key) const noexcept {
+ std::size_t hash = 0;
+ for (auto byte : key) {
+ hash ^= std::hash{}(byte) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
+ }
+ return hash;
+ }
+};
+
+struct uchar_array_equal {
+ bool operator()(const std::array& lhs, const std::array& rhs) const noexcept {
+ return lhs == rhs;
+ }
+};
+
+// 定义 HashTable 类型
+typedef robin_hood::unordered_map, uint64_t, uchar_array_hash, uchar_array_equal> HashTable;
+
+void print_pair(const Pair &data){
+ std::cout << "value:" << data.enc_val << std::endl;
+ std::cout << "value:" << data.cmac << std::endl;
+}
+
+void print_array(const std::array& arr) {
+ // for (const auto& byte : arr) {
+ // std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(byte) << ' ';
+ // }
+ // std::cout << std::dec << std::endl; // Reset to decimal format
+ for(unsigned char a : arr){
+ std::cout << a;
+ }
+ std::cout << std::endl;
+}
+
+void print_hash_table(uint64_t table_addr){
+ HashTable * hash_table = (HashTable *)table_addr;
+ for (const auto& entry : *hash_table) {
+ uint64_t pair_addr = entry.second;
+ Pair * data = (Pair *)pair_addr;
+ std::cout << "Key: ";
+ print_array(entry.first);
+ std::cout << "Value: ";
+ for (int i = 0; i < data->value_size; ++i) std::cout << data->enc_val[i];
+ std::cout << std::endl;
+ std::cout << "CMAC: ";
+ for (int i = 0; i < 16; ++i) std::cout << data->cmac[i];
+ std::cout << std::endl;
+ std::cout << "——————————————————————————————————" << std::endl;
+ }
+}
+
+void print1(uint64_t addr){
+ std::cout << "address in enclave:" << addr << std::endl;
+}
+
+void print(unsigned char* iv_test){
+ int key_len = strlen((char *)iv_test);
+ std::cout << "str in enclave:" << iv_test << std::endl;
+ // std::cout << "len in print:" << key_len << std::endl;
+ // std::array cipher_key_arr={};
+ // std::cout << "len" << key_len << std::endl;
+ // memcpy(cipher_key_arr.data(), iv_test, key_len);
+ // print_array(cipher_key_arr);
+
+}
+
+void pirnt_inst(uint64_t a){
+ char ***instructions = (char ***)a;
+ for(int i = 0;i < 5;i++){
+ std::cout << "key:" << instructions[i][1] << std::endl;
+ }
+}
+
+void printstr(char* str){
+ std::cout << "str in enclave:" << str << std::endl;
+}
+
+void printint(int a){
+ std::cout << "int in enclave:" << a << std::endl;
+}
+
+int main()
+{
+ int retval = 0;
+ char *path = PATH;
+ char buf[BUF_LEN];
+ cc_enclave_t context = {};
+ cc_enclave_result_t res = CC_FAIL;
+
+ char real_p[PATH_MAX];
+ /* check file exists, if not exist then use absolute path */
+ if (realpath(path, real_p) == NULL) {
+ if (getcwd(real_p, sizeof(real_p)) == NULL) {
+ printf("Cannot find enclave.sign.so");
+ // goto end;
+ return res;
+ }
+ if (PATH_MAX - strlen(real_p) <= strlen("/enclave.signed.so")) {
+ printf("Failed to strcat enclave.sign.so path");
+ // goto end;
+ return res;
+ }
+ (void)strcat(real_p, "/enclave.signed.so");
+ }
+
+ res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
+ if (res != CC_SUCCESS) {
+ printf("host create enclave error\n");
+ // goto end;
+ return res;
+ }
+ printf("host create enclave success\n");
+
+
+ // //////
+ // 在非安全区分配内存
+
+ // 初始化
+ initEnclave(&context);
+
+ // 开放的两个接口的调用测试
+
+ // char testkey[32] = "my name is qiqi";
+ // char testvalue[32] = "qikiqikiqiki";
+
+ // Pair * hi = new Pair();
+ // SET_KV_Pair(&context, testkey, testvalue, (uint64_t)hi);
+
+
+ // char testkey2[32] = "my name is qiaqia";
+ // char testvalue2[32] = "club club qiaqiaqia";
+
+ // Pair * ha = new Pair();
+ // SET_KV_Pair(&context, testkey2, testvalue2, (uint64_t)ha);
+
+ // unsigned char plain[32]={};
+
+ // GET_KV_Pair(&context, testkey, plain);
+ // std::cout << plain << std::endl;
+
+ // GET_KV_Pair(&context, testkey2, plain);
+ // std::cout << plain << std::endl;
+
+
+ // 实验跑数据测试代码
+ // ////////////////////////////////////////////////////////////////////////////////////////////////////
+ // 加载load数据 开始
+ std::cout << "start loading the load workload......" << std::endl;
+
+ std::ifstream ifs;
+ ifs.open("/home/bulv/bulv_workstation/workloads/processed_load_workload.txt", std::ios::in);
+ if (!ifs.is_open()) {
+ std::cerr << "无法打开文件!" << strerror(errno) << std::endl;
+ return 1;
+ }
+
+ std::string line;
+ char* get_key = nullptr;
+ char* set_key = nullptr;
+ char* set_value = nullptr;
+
+ while (std::getline(ifs, line)) { // 按行读取文件
+ std::istringstream iss(line);
+ std::string command;
+ iss >> command; // 读取命令 (GET 或 SET)
+
+ if (command == "SET") {
+ std::string key = line.substr(4,16);
+ std::string value = line.substr(21,16);
+ set_key = new char[key.size() + 1];
+ set_value = new char[value.size() + 1];
+
+ strcpy(set_key, key.c_str()); // 将 key 复制到 set_key
+ strcpy(set_value, value.c_str()); // 将 value 复制到 set_value
+ // std::cout << strlen(set_value) << std::endl;
+ // setkey
+ Pair * pair = new Pair();
+ set_key[16]= '\0';
+ SET_KV_Pair(&context, set_key, set_value, (uint64_t)pair);
+ // std::cout << pair->enc_val << std::endl;
+ // std::cout << "encvalue:" << pair->enc_val << std::endl;
+ // std::cout << "SET key: " << set_key << ", value: " << set_value << std::endl;
+ }
+ }
+
+ // 释放内存
+ delete[] get_key;
+ delete[] set_key;
+ delete[] set_value;
+
+ ifs.close(); // 关闭文件
+ std::cout << "end loading the load workload......" << std::endl;
+ // print_hash_table(table_addr);
+ // 加载load数据及结束
+ // ////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // ////////////////////////////////////////////////////////////////////////////////////////////////////
+ // load 这么加载没啥问题,load又不算时间 可以先不改
+ // 需要先分配一些内存,将文件里的指令加载到内存中,再存储一个指针,指向这些区域的一个地址,传入安全区再进行分割和处理
+ std::cout << "start loading the run workload......" << std::endl;
+ char ***instructions = (char ***)malloc(NUM_INSTRUCTIONS * sizeof(char**));
+ if(!instructions){
+ printf("Instruction memory allocation failed!");
+ }
+ for(int i = 0; i < NUM_INSTRUCTIONS; i++){
+ instructions[i] = (char**)malloc(3 * sizeof(char*));
+ instructions[i][0] = (char *)malloc(4*sizeof(char));
+ instructions[i][1] = (char *)malloc((KEY_SIZE+1)*sizeof(char));
+ instructions[i][2] = (char *)malloc((VALUE_SIZE+1)*sizeof(char));
+ }
+ // 预先分配好Pair的地址
+ Pair *pairs = (Pair *)malloc(NUM_INSTRUCTIONS * sizeof(Pair));
+ if(!pairs){
+ printf("pair memory allocation failed!");
+ }
+ Pair **pair_array = (Pair **)malloc(NUM_INSTRUCTIONS * sizeof(Pair*));
+ if(!pair_array){
+ printf("pair_array memory allocation failed!");
+ }
+ for(size_t i = 0; i < NUM_INSTRUCTIONS; i++){
+ pair_array[i]= &pairs[i];
+ }
+ // 内存分配完毕,开始读取文件
+ FILE *fp = fopen("/home/bulv/bulv_workstation/workloads/processed_run_workload.txt","r");
+ char buff[BUF_SIZE];
+ int i = 0;
+ while(fgets(buff, BUF_SIZE, fp) != NULL && i < NUM_INSTRUCTIONS) {
+ // 去掉换行符
+ size_t len = strlen(buff);
+ if (len > 0 && buff[len - 1] == '\n') {
+ buff[len - 1] = '\0';
+ }
+
+
+ // 分割操作
+ char *operation = strtok(buff, " ");
+ if (operation != NULL) {
+ strcpy(instructions[i][0], operation);
+ // std::cout << instructions[i][0] << std::endl;
+
+ char *readkey = strtok(NULL, " ");
+ if (readkey != NULL) {
+ strcpy(instructions[i][1], readkey);
+ instructions[i][1][KEY_SIZE] = '\0';
+ // std::cout << instructions[i][1] << std::endl;
+
+ if (strcmp(operation, "SET") == 0) {
+ // 提取 value 部分
+ char *value_start = strtok(NULL, "");
+ if (value_start != NULL) {
+ // 确保 value 被正确提取
+ strncpy(instructions[i][2], value_start, VALUE_SIZE);
+ instructions[i][2][VALUE_SIZE] = '\0';
+ } else {
+ strcpy(instructions[i][2], "");
+ }
+ // std::cout << instructions[i][2] << std::endl;
+ } else {
+ strcpy(instructions[i][2], "");
+ }
+ }
+ i++;
+ }
+ }
+ fclose(fp);
+ std::cout << "end loading the run workload......" << std::endl;
+ // //////////////////////
+
+ timeval start,end;
+ gettimeofday(&start,NULL);
+ process_workload(&context,(uint64_t)instructions,(uint64_t)pair_array);
+ gettimeofday(&end,NULL);
+ long seconds = end.tv_sec - start.tv_sec;
+ long microseconds = end.tv_usec - start.tv_usec;
+ if(microseconds < 0){
+ seconds -= 1;
+ microseconds += 1000000;
+ }
+ double totalTime = seconds + microseconds / 1000000.0;
+ std::cout << "运行时间:" << seconds << "秒" << microseconds << "微秒" << std::endl;
+ std::cout << "运行时间:" << totalTime << "s" << std::endl;
+ // 释放内存
+ // for(int j = 0; j < NUM_INSTRUCTIONS; j++){
+ // free(instructions[i][0]);
+ // free(instructions[i][1]);
+ // free(instructions[i][2]);
+ // free(instructions[i]);
+ // }
+ free(instructions);
+
+ /////////////////////////
+ res = cc_enclave_destroy(&context);
+ if(res != CC_SUCCESS) {
+ printf("host destroy enclave error\n");
+ } else {
+ printf("host destroy enclave success\n");
+ }
+// end:
+// return res;
+}
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/include/common.h" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/include/common.h"
new file mode 100644
index 0000000000000000000000000000000000000000..d8a984db51d1fe6b33deba698991e01ca6bed208
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/include/common.h"
@@ -0,0 +1,29 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#define VALUE_SIZE 128
+#define TEST_ITEM_SIZE 1000000
+using namespace std;
+
+// 键(存储在TEE中)
+typedef struct KEY {
+ int key_val; // 键
+ uint8_t *val_ptr; // 指针
+ size_t val_size; // value长度
+ size_t hash_value; // hash(这里可以选一种hash函数替换成HMAC)
+} KEY;
+
+// 值(加密存储在REE中)
+typedef struct VALUE {
+ uint8_t *value;
+ size_t val_len;
+} VALUE;
+
+// 键值对数据
+typedef struct KV {
+ int32_t key_val;
+ uint8_t value[VALUE_SIZE];
+ size_t value_len;
+} KV;
+
+#endif
\ No newline at end of file
diff --git "a/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/include/robin_hood.h" "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/include/robin_hood.h"
new file mode 100644
index 0000000000000000000000000000000000000000..0af031f5f4a9fbacdf63689296f7ed847f83fa92
--- /dev/null
+++ "b/summer2024\345\237\272\344\272\216secGear\347\232\204\351\253\230\346\225\210KV\345\255\230\345\202\250\346\225\260\346\215\256\347\273\223\346\236\204\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260/hope/include/robin_hood.h"
@@ -0,0 +1,2544 @@
+// ______ _____ ______ _________
+// ______________ ___ /_ ___(_)_______ ___ /_ ______ ______ ______ /
+// __ ___/_ __ \__ __ \__ / __ __ \ __ __ \_ __ \_ __ \_ __ /
+// _ / / /_/ /_ /_/ /_ / _ / / / _ / / // /_/ // /_/ // /_/ /
+// /_/ \____/ /_.___/ /_/ /_/ /_/ ________/_/ /_/ \____/ \____/ \__,_/
+// _/_____/
+//
+// Fast & memory efficient hashtable based on robin hood hashing for C++11/14/17/20
+// https://github.com/martinus/robin-hood-hashing
+//
+// Licensed under the MIT License .
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2018-2021 Martin Ankerl
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef ROBIN_HOOD_H_INCLUDED
+#define ROBIN_HOOD_H_INCLUDED
+
+// see https://semver.org/
+#define ROBIN_HOOD_VERSION_MAJOR 3 // for incompatible API changes
+#define ROBIN_HOOD_VERSION_MINOR 11 // for adding functionality in a backwards-compatible manner
+#define ROBIN_HOOD_VERSION_PATCH 5 // for backwards-compatible bug fixes
+
+#include
+#include
+#include
+#include
+#include
+#include // only to support hash of smart pointers
+#include
+#include
+#include
+#include
+#if __cplusplus >= 201703L
+# include
+#endif
+
+// #define ROBIN_HOOD_LOG_ENABLED
+#ifdef ROBIN_HOOD_LOG_ENABLED
+# include
+# define ROBIN_HOOD_LOG(...) \
+ std::cout << __FUNCTION__ << "@" << __LINE__ << ": " << __VA_ARGS__ << std::endl;
+#else
+# define ROBIN_HOOD_LOG(x)
+#endif
+
+// #define ROBIN_HOOD_TRACE_ENABLED
+#ifdef ROBIN_HOOD_TRACE_ENABLED
+# include
+# define ROBIN_HOOD_TRACE(...) \
+ std::cout << __FUNCTION__ << "@" << __LINE__ << ": " << __VA_ARGS__ << std::endl;
+#else
+# define ROBIN_HOOD_TRACE(x)
+#endif
+
+// #define ROBIN_HOOD_COUNT_ENABLED
+#ifdef ROBIN_HOOD_COUNT_ENABLED
+# include
+# define ROBIN_HOOD_COUNT(x) ++counts().x;
+namespace robin_hood {
+struct Counts {
+ uint64_t shiftUp{};
+ uint64_t shiftDown{};
+};
+inline std::ostream& operator<<(std::ostream& os, Counts const& c) {
+ return os << c.shiftUp << " shiftUp" << std::endl << c.shiftDown << " shiftDown" << std::endl;
+}
+
+static Counts& counts() {
+ static Counts counts{};
+ return counts;
+}
+} // namespace robin_hood
+#else
+# define ROBIN_HOOD_COUNT(x)
+#endif
+
+// all non-argument macros should use this facility. See
+// https://www.fluentcpp.com/2019/05/28/better-macros-better-flags/
+#define ROBIN_HOOD(x) ROBIN_HOOD_PRIVATE_DEFINITION_##x()
+
+// mark unused members with this macro
+#define ROBIN_HOOD_UNUSED(identifier)
+
+// bitness
+#if SIZE_MAX == UINT32_MAX
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITNESS() 32
+#elif SIZE_MAX == UINT64_MAX
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITNESS() 64
+#else
+# error Unsupported bitness
+#endif
+
+// endianess
+#ifdef _MSC_VER
+# define ROBIN_HOOD_PRIVATE_DEFINITION_LITTLE_ENDIAN() 1
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BIG_ENDIAN() 0
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_LITTLE_ENDIAN() \
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BIG_ENDIAN() (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#endif
+
+// inline
+#ifdef _MSC_VER
+# define ROBIN_HOOD_PRIVATE_DEFINITION_NOINLINE() __declspec(noinline)
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_NOINLINE() __attribute__((noinline))
+#endif
+
+// exceptions
+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND)
+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_EXCEPTIONS() 0
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_EXCEPTIONS() 1
+#endif
+
+// count leading/trailing bits
+#if !defined(ROBIN_HOOD_DISABLE_INTRINSICS)
+# ifdef _MSC_VER
+# if ROBIN_HOOD(BITNESS) == 32
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITSCANFORWARD() _BitScanForward
+# else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITSCANFORWARD() _BitScanForward64
+# endif
+# include
+# pragma intrinsic(ROBIN_HOOD(BITSCANFORWARD))
+# define ROBIN_HOOD_COUNT_TRAILING_ZEROES(x) \
+ [](size_t mask) noexcept -> int { \
+ unsigned long index; \
+ return ROBIN_HOOD(BITSCANFORWARD)(&index, mask) ? static_cast(index) \
+ : ROBIN_HOOD(BITNESS); \
+ }(x)
+# else
+# if ROBIN_HOOD(BITNESS) == 32
+# define ROBIN_HOOD_PRIVATE_DEFINITION_CTZ() __builtin_ctzl
+# define ROBIN_HOOD_PRIVATE_DEFINITION_CLZ() __builtin_clzl
+# else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_CTZ() __builtin_ctzll
+# define ROBIN_HOOD_PRIVATE_DEFINITION_CLZ() __builtin_clzll
+# endif
+# define ROBIN_HOOD_COUNT_LEADING_ZEROES(x) ((x) ? ROBIN_HOOD(CLZ)(x) : ROBIN_HOOD(BITNESS))
+# define ROBIN_HOOD_COUNT_TRAILING_ZEROES(x) ((x) ? ROBIN_HOOD(CTZ)(x) : ROBIN_HOOD(BITNESS))
+# endif
+#endif
+
+// fallthrough
+#ifndef __has_cpp_attribute // For backwards compatibility
+# define __has_cpp_attribute(x) 0
+#endif
+#if __has_cpp_attribute(clang::fallthrough)
+# define ROBIN_HOOD_PRIVATE_DEFINITION_FALLTHROUGH() [[clang::fallthrough]]
+#elif __has_cpp_attribute(gnu::fallthrough)
+# define ROBIN_HOOD_PRIVATE_DEFINITION_FALLTHROUGH() [[gnu::fallthrough]]
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_FALLTHROUGH()
+#endif
+
+// likely/unlikely
+#ifdef _MSC_VER
+# define ROBIN_HOOD_LIKELY(condition) condition
+# define ROBIN_HOOD_UNLIKELY(condition) condition
+#else
+# define ROBIN_HOOD_LIKELY(condition) __builtin_expect(condition, 1)
+# define ROBIN_HOOD_UNLIKELY(condition) __builtin_expect(condition, 0)
+#endif
+
+// detect if native wchar_t type is availiable in MSVC
+#ifdef _MSC_VER
+# ifdef _NATIVE_WCHAR_T_DEFINED
+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_NATIVE_WCHART() 1
+# else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_NATIVE_WCHART() 0
+# endif
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_NATIVE_WCHART() 1
+#endif
+
+// detect if MSVC supports the pair(std::piecewise_construct_t,...) consructor being constexpr
+#ifdef _MSC_VER
+# if _MSC_VER <= 1900
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BROKEN_CONSTEXPR() 1
+# else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BROKEN_CONSTEXPR() 0
+# endif
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_BROKEN_CONSTEXPR() 0
+#endif
+
+// workaround missing "is_trivially_copyable" in g++ < 5.0
+// See https://stackoverflow.com/a/31798726/48181
+#if defined(__GNUC__) && __GNUC__ < 5
+# define ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__)
+#else
+# define ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(...) std::is_trivially_copyable<__VA_ARGS__>::value
+#endif
+
+// helpers for C++ versions, see https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX() __cplusplus
+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX98() 199711L
+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX11() 201103L
+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX14() 201402L
+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX17() 201703L
+
+#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX17)
+# define ROBIN_HOOD_PRIVATE_DEFINITION_NODISCARD() [[nodiscard]]
+#else
+# define ROBIN_HOOD_PRIVATE_DEFINITION_NODISCARD()
+#endif
+
+namespace robin_hood {
+
+#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX14)
+# define ROBIN_HOOD_STD std
+#else
+
+// c++11 compatibility layer
+namespace ROBIN_HOOD_STD {
+template
+struct alignment_of
+ : std::integral_constant::type)> {};
+
+template
+class integer_sequence {
+public:
+ using value_type = T;
+ static_assert(std::is_integral::value, "not integral type");
+ static constexpr std::size_t size() noexcept {
+ return sizeof...(Ints);
+ }
+};
+template
+using index_sequence = integer_sequence;
+
+namespace detail_ {
+template
+struct IntSeqImpl {
+ using TValue = T;
+ static_assert(std::is_integral::value, "not integral type");
+ static_assert(Begin >= 0 && Begin < End, "unexpected argument (Begin<0 || Begin<=End)");
+
+ template
+ struct IntSeqCombiner;
+
+ template
+ struct IntSeqCombiner, integer_sequence> {
+ using TResult = integer_sequence;
+ };
+
+ using TResult =
+ typename IntSeqCombiner::TResult,
+ typename IntSeqImpl::TResult>::TResult;
+};
+
+template
+struct IntSeqImpl {
+ using TValue = T;
+ static_assert(std::is_integral::value, "not integral type");
+ static_assert(Begin >= 0, "unexpected argument (Begin<0)");
+ using TResult = integer_sequence;
+};
+
+template
+struct IntSeqImpl {
+ using TValue = T;
+ static_assert(std::is_integral::value, "not integral type");
+ static_assert(Begin >= 0, "unexpected argument (Begin<0)");
+ using TResult = integer_sequence;
+};
+} // namespace detail_
+
+template
+using make_integer_sequence = typename detail_::IntSeqImpl::TResult;
+
+template
+using make_index_sequence = make_integer_sequence;
+
+template
+using index_sequence_for = make_index_sequence;
+
+} // namespace ROBIN_HOOD_STD
+
+#endif
+
+namespace detail {
+
+// make sure we static_cast to the correct type for hash_int
+#if ROBIN_HOOD(BITNESS) == 64
+using SizeT = uint64_t;
+#else
+using SizeT = uint32_t;
+#endif
+
+template
+T rotr(T x, unsigned k) {
+ return (x >> k) | (x << (8U * sizeof(T) - k));
+}
+
+// This cast gets rid of warnings like "cast from 'uint8_t*' {aka 'unsigned char*'} to
+// 'uint64_t*' {aka 'long unsigned int*'} increases required alignment of target type". Use with
+// care!
+template
+inline T reinterpret_cast_no_cast_align_warning(void* ptr) noexcept {
+ return reinterpret_cast(ptr);
+}
+
+template
+inline T reinterpret_cast_no_cast_align_warning(void const* ptr) noexcept {
+ return reinterpret_cast(ptr);
+}
+
+// make sure this is not inlined as it is slow and dramatically enlarges code, thus making other
+// inlinings more difficult. Throws are also generally the slow path.
+template
+[[noreturn]] ROBIN_HOOD(NOINLINE)
+#if ROBIN_HOOD(HAS_EXCEPTIONS)
+ void doThrow(Args&&... args) {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
+ throw E(std::forward(args)...);
+}
+#else
+ void doThrow(Args&&... ROBIN_HOOD_UNUSED(args) /*unused*/) {
+ abort();
+}
+#endif
+
+template
+T* assertNotNull(T* t, Args&&... args) {
+ if (ROBIN_HOOD_UNLIKELY(nullptr == t)) {
+ doThrow(std::forward(args)...);
+ }
+ return t;
+}
+
+template
+inline T unaligned_load(void const* ptr) noexcept {
+ // using memcpy so we don't get into unaligned load problems.
+ // compiler should optimize this very well anyways.
+ T t;
+ std::memcpy(&t, ptr, sizeof(T));
+ return t;
+}
+
+// Allocates bulks of memory for objects of type T. This deallocates the memory in the destructor,
+// and keeps a linked list of the allocated memory around. Overhead per allocation is the size of a
+// pointer.
+template
+class BulkPoolAllocator {
+public:
+ BulkPoolAllocator() noexcept = default;
+
+ // does not copy anything, just creates a new allocator.
+ BulkPoolAllocator(const BulkPoolAllocator& ROBIN_HOOD_UNUSED(o) /*unused*/) noexcept
+ : mHead(nullptr)
+ , mListForFree(nullptr) {}
+
+ BulkPoolAllocator(BulkPoolAllocator&& o) noexcept
+ : mHead(o.mHead)
+ , mListForFree(o.mListForFree) {
+ o.mListForFree = nullptr;
+ o.mHead = nullptr;
+ }
+
+ BulkPoolAllocator& operator=(BulkPoolAllocator&& o) noexcept {
+ reset();
+ mHead = o.mHead;
+ mListForFree = o.mListForFree;
+ o.mListForFree = nullptr;
+ o.mHead = nullptr;
+ return *this;
+ }
+
+ BulkPoolAllocator&
+ // NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
+ operator=(const BulkPoolAllocator& ROBIN_HOOD_UNUSED(o) /*unused*/) noexcept {
+ // does not do anything
+ return *this;
+ }
+
+ ~BulkPoolAllocator() noexcept {
+ reset();
+ }
+
+ // Deallocates all allocated memory.
+ void reset() noexcept {
+ while (mListForFree) {
+ T* tmp = *mListForFree;
+ ROBIN_HOOD_LOG("std::free")
+ std::free(mListForFree);
+ mListForFree = reinterpret_cast_no_cast_align_warning(tmp);
+ }
+ mHead = nullptr;
+ }
+
+ // allocates, but does NOT initialize. Use in-place new constructor, e.g.
+ // T* obj = pool.allocate();
+ // ::new (static_cast(obj)) T();
+ T* allocate() {
+ T* tmp = mHead;
+ if (!tmp) {
+ tmp = performAllocation();
+ }
+
+ mHead = *reinterpret_cast_no_cast_align_warning(tmp);
+ return tmp;
+ }
+
+ // does not actually deallocate but puts it in store.
+ // make sure you have already called the destructor! e.g. with
+ // obj->~T();
+ // pool.deallocate(obj);
+ void deallocate(T* obj) noexcept {
+ *reinterpret_cast_no_cast_align_warning(obj) = mHead;
+ mHead = obj;
+ }
+
+ // Adds an already allocated block of memory to the allocator. This allocator is from now on
+ // responsible for freeing the data (with free()). If the provided data is not large enough to
+ // make use of, it is immediately freed. Otherwise it is reused and freed in the destructor.
+ void addOrFree(void* ptr, const size_t numBytes) noexcept {
+ // calculate number of available elements in ptr
+ if (numBytes < ALIGNMENT + ALIGNED_SIZE) {
+ // not enough data for at least one element. Free and return.
+ ROBIN_HOOD_LOG("std::free")
+ std::free(ptr);
+ } else {
+ ROBIN_HOOD_LOG("add to buffer")
+ add(ptr, numBytes);
+ }
+ }
+
+ void swap(BulkPoolAllocator& other) noexcept {
+ using std::swap;
+ swap(mHead, other.mHead);
+ swap(mListForFree, other.mListForFree);
+ }
+
+private:
+ // iterates the list of allocated memory to calculate how many to alloc next.
+ // Recalculating this each time saves us a size_t member.
+ // This ignores the fact that memory blocks might have been added manually with addOrFree. In
+ // practice, this should not matter much.
+ ROBIN_HOOD(NODISCARD) size_t calcNumElementsToAlloc() const noexcept {
+ auto tmp = mListForFree;
+ size_t numAllocs = MinNumAllocs;
+
+ while (numAllocs * 2 <= MaxNumAllocs && tmp) {
+ auto x = reinterpret_cast(tmp);
+ tmp = *x;
+ numAllocs *= 2;
+ }
+
+ return numAllocs;
+ }
+
+ // WARNING: Underflow if numBytes < ALIGNMENT! This is guarded in addOrFree().
+ void add(void* ptr, const size_t numBytes) noexcept {
+ const size_t numElements = (numBytes - ALIGNMENT) / ALIGNED_SIZE;
+
+ auto data = reinterpret_cast(ptr);
+
+ // link free list
+ auto x = reinterpret_cast(data);
+ *x = mListForFree;
+ mListForFree = data;
+
+ // create linked list for newly allocated data
+ auto* const headT =
+ reinterpret_cast_no_cast_align_warning(reinterpret_cast(ptr) + ALIGNMENT);
+
+ auto* const head = reinterpret_cast(headT);
+
+ // Visual Studio compiler automatically unrolls this loop, which is pretty cool
+ for (size_t i = 0; i < numElements; ++i) {
+ *reinterpret_cast_no_cast_align_warning(head + i * ALIGNED_SIZE) =
+ head + (i + 1) * ALIGNED_SIZE;
+ }
+
+ // last one points to 0
+ *reinterpret_cast_no_cast_align_warning(head + (numElements - 1) * ALIGNED_SIZE) =
+ mHead;
+ mHead = headT;
+ }
+
+ // Called when no memory is available (mHead == 0).
+ // Don't inline this slow path.
+ ROBIN_HOOD(NOINLINE) T* performAllocation() {
+ size_t const numElementsToAlloc = calcNumElementsToAlloc();
+
+ // alloc new memory: [prev |T, T, ... T]
+ size_t const bytes = ALIGNMENT + ALIGNED_SIZE * numElementsToAlloc;
+ ROBIN_HOOD_LOG("std::malloc " << bytes << " = " << ALIGNMENT << " + " << ALIGNED_SIZE
+ << " * " << numElementsToAlloc)
+ add(assertNotNull(std::malloc(bytes)), bytes);
+ return mHead;
+ }
+
+ // enforce byte alignment of the T's
+#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX14)
+ static constexpr size_t ALIGNMENT =
+ (std::max)(std::alignment_of::value, std::alignment_of::value);
+#else
+ static const size_t ALIGNMENT =
+ (ROBIN_HOOD_STD::alignment_of::value > ROBIN_HOOD_STD::alignment_of::value)
+ ? ROBIN_HOOD_STD::alignment_of::value
+ : +ROBIN_HOOD_STD::alignment_of::value; // the + is for walkarround
+#endif
+
+ static constexpr size_t ALIGNED_SIZE = ((sizeof(T) - 1) / ALIGNMENT + 1) * ALIGNMENT;
+
+ static_assert(MinNumAllocs >= 1, "MinNumAllocs");
+ static_assert(MaxNumAllocs >= MinNumAllocs, "MaxNumAllocs");
+ static_assert(ALIGNED_SIZE >= sizeof(T*), "ALIGNED_SIZE");
+ static_assert(0 == (ALIGNED_SIZE % sizeof(T*)), "ALIGNED_SIZE mod");
+ static_assert(ALIGNMENT >= sizeof(T*), "ALIGNMENT");
+
+ T* mHead{nullptr};
+ T** mListForFree{nullptr};
+};
+
+template
+struct NodeAllocator;
+
+// dummy allocator that does nothing
+template
+struct NodeAllocator {
+
+ // we are not using the data, so just free it.
+ void addOrFree(void* ptr, size_t ROBIN_HOOD_UNUSED(numBytes) /*unused*/) noexcept {
+ ROBIN_HOOD_LOG("std::free")
+ std::free(ptr);
+ }
+};
+
+template
+struct NodeAllocator : public BulkPoolAllocator {};
+
+// c++14 doesn't have is_nothrow_swappable, and clang++ 6.0.1 doesn't like it either, so I'm making
+// my own here.
+namespace swappable {
+#if ROBIN_HOOD(CXX) < ROBIN_HOOD(CXX17)
+using std::swap;
+template
+struct nothrow {
+ static const bool value = noexcept(swap(std::declval(), std::declval()));
+};
+#else
+template
+struct nothrow {
+ static const bool value = std::is_nothrow_swappable::value;
+};
+#endif
+} // namespace swappable
+
+} // namespace detail
+
+struct is_transparent_tag {};
+
+// A custom pair implementation is used in the map because std::pair is not is_trivially_copyable,
+// which means it would not be allowed to be used in std::memcpy. This struct is copyable, which is
+// also tested.
+template
+struct pair {
+ using first_type = T1;
+ using second_type = T2;
+
+ template ::value &&
+ std::is_default_constructible::value>::type>
+ constexpr pair() noexcept(noexcept(U1()) && noexcept(U2()))
+ : first()
+ , second() {}
+
+ // pair constructors are explicit so we don't accidentally call this ctor when we don't have to.
+ explicit constexpr pair(std::pair const& o) noexcept(
+ noexcept(T1(std::declval())) && noexcept(T2(std::declval())))
+ : first(o.first)
+ , second(o.second) {}
+
+ // pair constructors are explicit so we don't accidentally call this ctor when we don't have to.
+ explicit constexpr pair(std::pair&& o) noexcept(noexcept(
+ T1(std::move(std::declval()))) && noexcept(T2(std::move(std::declval()))))
+ : first(std::move(o.first))
+ , second(std::move(o.second)) {}
+
+ constexpr pair(T1&& a, T2&& b) noexcept(noexcept(
+ T1(std::move(std::declval()))) && noexcept(T2(std::move(std::declval()))))
+ : first(std::move(a))
+ , second(std::move(b)) {}
+
+ template
+ constexpr pair(U1&& a, U2&& b) noexcept(noexcept(T1(std::forward(
+ std::declval()))) && noexcept(T2(std::forward(std::declval()))))
+ : first(std::forward(a))
+ , second(std::forward(b)) {}
+
+ template
+ // MSVC 2015 produces error "C2476: ‘constexpr’ constructor does not initialize all members"
+ // if this constructor is constexpr
+#if !ROBIN_HOOD(BROKEN_CONSTEXPR)
+ constexpr
+#endif
+ pair(std::piecewise_construct_t /*unused*/, std::tuple a,
+ std::tuple
+ b) noexcept(noexcept(pair(std::declval&>(),
+ std::declval&>(),
+ ROBIN_HOOD_STD::index_sequence_for(),
+ ROBIN_HOOD_STD::index_sequence_for())))
+ : pair(a, b, ROBIN_HOOD_STD::index_sequence_for(),
+ ROBIN_HOOD_STD::index_sequence_for()) {
+ }
+
+ // constructor called from the std::piecewise_construct_t ctor
+ template
+ pair(std::tuple& a, std::tuple& b, ROBIN_HOOD_STD::index_sequence /*unused*/, ROBIN_HOOD_STD::index_sequence /*unused*/) noexcept(
+ noexcept(T1(std::forward(std::get(
+ std::declval&>()))...)) && noexcept(T2(std::
+ forward(std::get(
+ std::declval&>()))...)))
+ : first(std::forward(std::get(a))...)
+ , second(std::forward(std::get(b))...) {
+ // make visual studio compiler happy about warning about unused a & b.
+ // Visual studio's pair implementation disables warning 4100.
+ (void)a;
+ (void)b;
+ }
+
+ void swap(pair& o) noexcept((detail::swappable::nothrow::value) &&
+ (detail::swappable::nothrow::value)) {
+ using std::swap;
+ swap(first, o.first);
+ swap(second, o.second);
+ }
+
+ T1 first; // NOLINT(misc-non-private-member-variables-in-classes)
+ T2 second; // NOLINT(misc-non-private-member-variables-in-classes)
+};
+
+template
+inline void swap(pair& a, pair& b) noexcept(
+ noexcept(std::declval&>().swap(std::declval&>()))) {
+ a.swap(b);
+}
+
+template
+inline constexpr bool operator==(pair const& x, pair const& y) {
+ return (x.first == y.first) && (x.second == y.second);
+}
+template
+inline constexpr bool operator!=(pair const& x, pair const& y) {
+ return !(x == y);
+}
+template
+inline constexpr bool operator<(pair const& x, pair const& y) noexcept(noexcept(
+ std::declval() < std::declval()) && noexcept(std::declval() <
+ std::declval())) {
+ return x.first < y.first || (!(y.first < x.first) && x.second < y.second);
+}
+template
+inline constexpr bool operator>(pair const& x, pair const& y) {
+ return y < x;
+}
+template
+inline constexpr bool operator<=(pair const& x, pair const& y) {
+ return !(x > y);
+}
+template
+inline constexpr bool operator>=(pair const& x, pair const& y) {
+ return !(x < y);
+}
+
+inline size_t hash_bytes(void const* ptr, size_t len) noexcept {
+ static constexpr uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
+ static constexpr uint64_t seed = UINT64_C(0xe17a1465);
+ static constexpr unsigned int r = 47;
+
+ auto const* const data64 = static_cast(ptr);
+ uint64_t h = seed ^ (len * m);
+
+ size_t const n_blocks = len / 8;
+ for (size_t i = 0; i < n_blocks; ++i) {
+ auto k = detail::unaligned_load(data64 + i);
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h ^= k;
+ h *= m;
+ }
+
+ auto const* const data8 = reinterpret_cast(data64 + n_blocks);
+ switch (len & 7U) {
+ case 7:
+ h ^= static_cast(data8[6]) << 48U;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ case 6:
+ h ^= static_cast(data8[5]) << 40U;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ case 5:
+ h ^= static_cast(data8[4]) << 32U;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ case 4:
+ h ^= static_cast(data8[3]) << 24U;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ case 3:
+ h ^= static_cast(data8[2]) << 16U;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ case 2:
+ h ^= static_cast(data8[1]) << 8U;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ case 1:
+ h ^= static_cast(data8[0]);
+ h *= m;
+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH
+ default:
+ break;
+ }
+
+ h ^= h >> r;
+
+ // not doing the final step here, because this will be done by keyToIdx anyways
+ // h *= m;
+ // h ^= h >> r;
+ return static_cast(h);
+}
+
+inline size_t hash_int(uint64_t x) noexcept {
+ // tried lots of different hashes, let's stick with murmurhash3. It's simple, fast, well tested,
+ // and doesn't need any special 128bit operations.
+ x ^= x >> 33U;
+ x *= UINT64_C(0xff51afd7ed558ccd);
+ x ^= x >> 33U;
+
+ // not doing the final step here, because this will be done by keyToIdx anyways
+ // x *= UINT64_C(0xc4ceb9fe1a85ec53);
+ // x ^= x >> 33U;
+ return static_cast(x);
+}
+
+// A thin wrapper around std::hash, performing an additional simple mixing step of the result.
+template
+struct hash : public std::hash {
+ size_t operator()(T const& obj) const
+ noexcept(noexcept(std::declval>().operator()(std::declval()))) {
+ // call base hash
+ auto result = std::hash::operator()(obj);
+ // return mixed of that, to be save against identity has
+ return hash_int(static_cast(result));
+ }
+};
+
+template
+struct hash> {
+ size_t operator()(std::basic_string const& str) const noexcept {
+ return hash_bytes(str.data(), sizeof(CharT) * str.size());
+ }
+};
+
+#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX17)
+template
+struct hash> {
+ size_t operator()(std::basic_string_view const& sv) const noexcept {
+ return hash_bytes(sv.data(), sizeof(CharT) * sv.size());
+ }
+};
+#endif
+
+template
+struct hash {
+ size_t operator()(T* ptr) const noexcept {
+ return hash_int(reinterpret_cast(ptr));
+ }
+};
+
+template
+struct hash> {
+ size_t operator()(std::unique_ptr const& ptr) const noexcept {
+ return hash_int(reinterpret_cast(ptr.get()));
+ }
+};
+
+template
+struct hash> {
+ size_t operator()(std::shared_ptr const& ptr) const noexcept {
+ return hash_int(reinterpret_cast(ptr.get()));
+ }
+};
+
+template
+struct hash::value>::type> {
+ size_t operator()(Enum e) const noexcept {
+ using Underlying = typename std::underlying_type::type;
+ return hash{}(static_cast(e));
+ }
+};
+
+#define ROBIN_HOOD_HASH_INT(T) \
+ template <> \
+ struct hash { \
+ size_t operator()(T const& obj) const noexcept { \
+ return hash_int(static_cast(obj)); \
+ } \
+ }
+
+#if defined(__GNUC__) && !defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wuseless-cast"
+#endif
+// see https://en.cppreference.com/w/cpp/utility/hash
+ROBIN_HOOD_HASH_INT(bool);
+ROBIN_HOOD_HASH_INT(char);
+ROBIN_HOOD_HASH_INT(signed char);
+ROBIN_HOOD_HASH_INT(unsigned char);
+ROBIN_HOOD_HASH_INT(char16_t);
+ROBIN_HOOD_HASH_INT(char32_t);
+#if ROBIN_HOOD(HAS_NATIVE_WCHART)
+ROBIN_HOOD_HASH_INT(wchar_t);
+#endif
+ROBIN_HOOD_HASH_INT(short);
+ROBIN_HOOD_HASH_INT(unsigned short);
+ROBIN_HOOD_HASH_INT(int);
+ROBIN_HOOD_HASH_INT(unsigned int);
+ROBIN_HOOD_HASH_INT(long);
+ROBIN_HOOD_HASH_INT(long long);
+ROBIN_HOOD_HASH_INT(unsigned long);
+ROBIN_HOOD_HASH_INT(unsigned long long);
+#if defined(__GNUC__) && !defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
+namespace detail {
+
+template
+struct void_type {
+ using type = void;
+};
+
+template
+struct has_is_transparent : public std::false_type {};
+
+template