From 76e1ba7f64cbda490d1df0f79bb20fae870a846c Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Thu, 25 Aug 2022 12:04:54 -0400 Subject: [PATCH 1/2] expose new crypto primitives currently only sha3 is exposed in crypto.hpp; add k1_recover, alt_bn128_add, alt_bn128_mul, alt_bn128_pair, and mod_exp to the header file. Those new primitives require crypto protocol feature to be activated. Seperate them from regular crypto.h and crypto.hpp so they are included only when needed. --- libraries/eosiolib/capi/eosio/crypto.h | 105 -------- libraries/eosiolib/capi/eosio/crypto_ext.h | 126 ++++++++++ libraries/eosiolib/core/eosio/crypto.hpp | 43 ---- libraries/eosiolib/core/eosio/crypto_ext.hpp | 226 ++++++++++++++++++ libraries/eosiolib/crypto.cpp | 47 +--- .../native/native/eosio/intrinsics_def.hpp | 1 + 6 files changed, 354 insertions(+), 194 deletions(-) create mode 100644 libraries/eosiolib/capi/eosio/crypto_ext.h create mode 100644 libraries/eosiolib/core/eosio/crypto_ext.hpp diff --git a/libraries/eosiolib/capi/eosio/crypto.h b/libraries/eosiolib/capi/eosio/crypto.h index 6dc6b71af4..fff817b79b 100644 --- a/libraries/eosiolib/capi/eosio/crypto.h +++ b/libraries/eosiolib/capi/eosio/crypto.h @@ -168,19 +168,6 @@ void sha1( const char* data, uint32_t length, struct capi_checksum160* hash ); __attribute__((eosio_wasm_import)) void sha512( const char* data, uint32_t length, struct capi_checksum512* hash ); -/** - * Hashes `data` using `sha3` and stores result in memory pointed to by hash. - * - * @param data - data you want to hash - * @param data_len - size of data - * @param hash - hash result - * @param hash_len - size of hash result - * @param keccak - whether to use `keccak` or NIST variant; keccak = 1 and NIST == 0 - * - */ -__attribute__((eosio_wasm_import)) -void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, int32_t keccak ); - /** * Hashes `data` using `ripemod160` and stores result in memory pointed to by hash. * @@ -199,28 +186,6 @@ void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, i __attribute__((eosio_wasm_import)) void ripemd160( const char* data, uint32_t length, struct capi_checksum160* hash ); -/** - * BLAKE2 compression function "F" - * https://eips.ethereum.org/EIPS/eip-152 - * - * @param rounds - the number of rounds - * @param state - state vector - * @param state_len - size of state vector - * @param msg - message block vector - * @param msg_len - size of message block vector - * @param t0_offset - offset counters - * @param t0_len - size of t0_offset - * @param t1_offset - offset counters - * @param t1_len - size of t1_offset - * @param final - final block flag - * @param result - the result of the compression - * @param result_len - size of result - * @return -1 if there is an error otherwise 0 - */ -__attribute__((eosio_wasm_import)) -int32_t blake2_f( uint32_t rounds, const char* state, uint32_t state_len, const char* msg, uint32_t msg_len, - const char* t0_offset, uint32_t t0_len, const char* t1_offset, uint32_t t1_len, int32_t final, char* result, uint32_t result_len); - /** * Calculates the public key used for a given signature and hash used to create a message. * @@ -267,76 +232,6 @@ int recover_key( const struct capi_checksum256* digest, const char* sig, size_t __attribute__((eosio_wasm_import)) void assert_recover_key( const struct capi_checksum256* digest, const char* sig, size_t siglen, const char* pub, size_t publen ); -/** - * Calculates the uncompressed public key used for a given signature on a given digest. - * - * @param sig - signature. - * @param sig_len - size of signature - * @param dig - digest of the message that was signed. - * @param dig_len - size of digest - * @param pub - public key result - * @param pub_len - size of public key result - * - * @return -1 if there was an error 0 otherwise. -*/ -int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len); - -/** - * Addition operation on the elliptic curve `alt_bn128` - * - * @param op1 - operand 1 - * @param op1_len - size of operand 1 - * @param op2 - operand 2 - * @param op2_len - size of operand 2 - * @param result - result of the addition operation - * @param result_len - size of result - * @return -1 if there is an error otherwise 0 - */ -__attribute__((eosio_wasm_import)) -int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len); - -/** - * Scalar multiplication operation on the elliptic curve `alt_bn128` - * - * @param g1 - G1 point - * @param g1_len - size of G1 point - * @param scalar - scalar factor - * @param scalar_len - size of scalar - * @param result - result of the scalar multiplication operation - * @param result_len - size of result - * @return -1 if there is an error otherwise 0 - */ -__attribute__((eosio_wasm_import)) -int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len); - -/** - * Optimal-Ate pairing check elliptic curve `alt_bn128` - * - * @param pairs - g1 and g2 pairs - * @param pairs_len - size of pairs - * @param result - result of the addition operation - * @return -1 if there is an error, 1 if false and 0 if true and successful - */ -__attribute__((eosio_wasm_import)) -int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len); - -/** - * Big integer modular exponentiation - * returns an output ( BASE^EXP ) % MOD - * - * @param base - base of the exponentiation (BASE) - * @param base_len - size of base - * @param exp - exponent to raise to that power (EXP) - * @param exp_len - size of exp - * @param mod - modulus (MOD) - * @param mod_len - size of mod - * @param result - result of the modular exponentiation - * @param result_len - size of result - * @return -1 if there is an error otherwise 0 - */ -__attribute__((eosio_wasm_import)) -int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len); - #ifdef __cplusplus } #endif diff --git a/libraries/eosiolib/capi/eosio/crypto_ext.h b/libraries/eosiolib/capi/eosio/crypto_ext.h new file mode 100644 index 0000000000..186a2c02aa --- /dev/null +++ b/libraries/eosiolib/capi/eosio/crypto_ext.h @@ -0,0 +1,126 @@ +/** + * @file + * @copyright defined in cdt/LICENSE + */ +#pragma once +#include "types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup crypto Crypto + * @brief Defines extension of %C API for calculating and checking hash which + * require activating crypto protocol feature + * @{ + */ + +/** + * Hashes `data` using `sha3` and stores result in memory pointed to by hash. + * + * @param data - data you want to hash + * @param data_len - size of data + * @param hash - hash result + * @param hash_len - size of hash result + * @param keccak - whether to use `keccak` or NIST variant; keccak = 1 and NIST == 0 + * + */ +__attribute__((eosio_wasm_import)) +void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, int32_t keccak ); + +/** + * BLAKE2 compression function "F" + * https://eips.ethereum.org/EIPS/eip-152 + * + * @param rounds - the number of rounds + * @param state - state vector + * @param state_len - size of state vector + * @param msg - message block vector + * @param msg_len - size of message block vector + * @param t0_offset - offset counters + * @param t0_len - size of t0_offset + * @param t1_offset - offset counters + * @param t1_len - size of t1_offset + * @param final - final block flag + * @param result - the result of the compression + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ +__attribute__((eosio_wasm_import)) +int32_t blake2_f( uint32_t rounds, const char* state, uint32_t state_len, const char* msg, uint32_t msg_len, + const char* t0_offset, uint32_t t0_len, const char* t1_offset, uint32_t t1_len, int32_t final, char* result, uint32_t result_len); + +/** + * Calculates the uncompressed public key used for a given signature on a given digest. + * + * @param sig - signature. + * @param sig_len - size of signature + * @param dig - digest of the message that was signed. + * @param dig_len - size of digest + * @param pub - public key result + * @param pub_len - size of public key result + * + * @return -1 if there was an error 0 otherwise. +*/ +int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len); + +/** + * Addition operation on the elliptic curve `alt_bn128` + * + * @param op1 - operand 1 + * @param op1_len - size of operand 1 + * @param op2 - operand 2 + * @param op2_len - size of operand 2 + * @param result - result of the addition operation + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ +__attribute__((eosio_wasm_import)) +int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len); + +/** + * Scalar multiplication operation on the elliptic curve `alt_bn128` + * + * @param g1 - G1 point + * @param g1_len - size of G1 point + * @param scalar - scalar factor + * @param scalar_len - size of scalar + * @param result - result of the scalar multiplication operation + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ +__attribute__((eosio_wasm_import)) +int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len); + +/** + * Optimal-Ate pairing check elliptic curve `alt_bn128` + * + * @param pairs - g1 and g2 pairs + * @param pairs_len - size of pairs + * @param result - result of the addition operation + * @return -1 if there is an error, 1 if false and 0 if true and successful + */ +__attribute__((eosio_wasm_import)) +int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len); + +/** + * Big integer modular exponentiation + * returns an output ( BASE^EXP ) % MOD + * + * @param base - base of the exponentiation (BASE) + * @param base_len - size of base + * @param exp - exponent to raise to that power (EXP) + * @param exp_len - size of exp + * @param mod - modulus (MOD) + * @param mod_len - size of mod + * @param result - result of the modular exponentiation + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ +__attribute__((eosio_wasm_import)) +int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len); + +#ifdef __cplusplus +} +#endif +/// @} diff --git a/libraries/eosiolib/core/eosio/crypto.hpp b/libraries/eosiolib/core/eosio/crypto.hpp index 56c1678763..b7ca46a980 100644 --- a/libraries/eosiolib/core/eosio/crypto.hpp +++ b/libraries/eosiolib/core/eosio/crypto.hpp @@ -276,49 +276,6 @@ namespace eosio { */ void assert_ripemd160( const char* data, uint32_t length, const eosio::checksum160& hash ); - /** - * Hashes `data` using SHA3 NIST. - * - * @ingroup crypto - * @param data - Data you want to hash - * @param length - Data length - * @return eosio::checksum256 - Computed digest - */ - eosio::checksum256 sha3( const char* data, uint32_t length ); - - /** - * Tests if the SHA3 hash generated from data matches the provided digest. - * - * @ingroup crypto - * @param data - Data you want to hash - * @param length - Data length - * @param hash - digest to compare to - * @note !This method is not optimized away during replay - */ - void assert_sha3( const char* data, uint32_t length, const eosio::checksum256& hash ); - - /** - * Hashes `data` using SHA3 Keccak. - * - * @ingroup crypto - * @param data - Data you want to hash - * @param length - Data length - * @return eosio::checksum256 - Computed digest - */ - eosio::checksum256 keccak( const char* data, uint32_t length ); - - /** - * Tests if the SHA3 keccak hash generated from data matches the provided digest. - * - * @ingroup crypto - * @param data - Data you want to hash - * @param length - Data length - * @param hash - digest to compare to - * @note !This method is not optimized away during replay - */ - void assert_keccak( const char* data, uint32_t length, const eosio::checksum256& hash ); - - /** * Hashes `data` using SHA256. * diff --git a/libraries/eosiolib/core/eosio/crypto_ext.hpp b/libraries/eosiolib/core/eosio/crypto_ext.hpp new file mode 100644 index 0000000000..a6dbe1211c --- /dev/null +++ b/libraries/eosiolib/core/eosio/crypto_ext.hpp @@ -0,0 +1,226 @@ +/** + * @file + * @copyright defined in cdt/LICENSE + */ +#pragma once + +#include "fixed_bytes.hpp" +#include "varint.hpp" +#include "serialize.hpp" + +#include + +namespace eosio { + + namespace internal_use_do_not_use { + extern "C" { + + struct __attribute__((aligned (16))) capi_checksum256 { uint8_t hash[32]; }; + + __attribute__((eosio_wasm_import)) + int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len); + + __attribute__((eosio_wasm_import)) + int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len); + + __attribute__((eosio_wasm_import)) + int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len); + + __attribute__((eosio_wasm_import)) + int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len); + + __attribute__((eosio_wasm_import)) + int32_t blake2_f( uint32_t rounds, const char* state, uint32_t state_len, const char* msg, uint32_t msg_len, const char* t0_offset, uint32_t t0_len, const char* t1_offset, uint32_t t1_len, int32_t final, char* result, uint32_t result_len); + + __attribute__((eosio_wasm_import)) + int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len); + + __attribute__((eosio_wasm_import)) + void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, int32_t keccak ); + } + + static inline auto sha3_helper(const char* data, uint32_t length, bool keccak) { + internal_use_do_not_use::capi_checksum256 hash; + internal_use_do_not_use::sha3( data, length, (char*)&hash, sizeof(hash), keccak); + eosio::checksum256 dg; + eosio::datastream ds = {&hash.hash[0], sizeof(hash)}; + ds >> dg; + return dg; + } + } + + /** + * @defgroup crypto Crypto + * @ingroup core + * @brief Defines API for calculating and checking hashes which + * require activating crypto protocol feature + */ + + /** + * Addition operation on the elliptic curve `alt_bn128` + * + * @ingroup crypto + * @param op1 - operand 1 + * @param op1_len - size of operand 1 + * @param op2 - operand 2 + * @param op2_len - size of operand 2 + * @param result - result of the addition operation + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ + inline int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len ) { + return internal_use_do_not_use::alt_bn128_add( op1, op1_len, op2, op2_len, result, result_len); + } + + /** + * Scalar multiplication operation on the elliptic curve `alt_bn128` + * + * @ingroup crypto + * @param g1 - G1 point + * @param g1_len - size of G1 point + * @param scalar - scalar factor + * @param scalar_len - size of scalar + * @param result - result of the scalar multiplication operation + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ + inline int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len ) { + return internal_use_do_not_use::alt_bn128_mul( g1, g1_len, scalar, scalar_len, result, result_len ); + } + + /** + * Optimal-Ate pairing check elliptic curve `alt_bn128` + * + * @ingroup crypto + * @param pairs - g1 and g2 pairs + * @param pairs_len - size of pairs + * @param result - result of the addition operation + * @return -1 if there is an error, 1 if false and 0 if true and successful + */ + inline int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len ) { + return internal_use_do_not_use::alt_bn128_pair( pairs, pairs_len ); + } + + /** + * Big integer modular exponentiation + * returns an output ( BASE^EXP ) % MOD + * + * @ingroup crypto + * @param base - base of the exponentiation (BASE) + * @param base_len - size of base + * @param exp - exponent to raise to that power (EXP) + * @param exp_len - size of exp + * @param mod - modulus (MOD) + * @param mod_len - size of mod + * @param result - result of the modular exponentiation + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ + + inline int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len ) { + return internal_use_do_not_use::mod_exp( base, base_len, exp, exp_len, mod, mod_len, result, result_len); + } + + /** + * BLAKE2 compression function "F" + * https://eips.ethereum.org/EIPS/eip-152 + * + * @ingroup crypto + * @param rounds - the number of rounds + * @param state - state vector + * @param state_len - size of state vector + * @param msg - message block vector + * @param msg_len - size of message block vector + * @param t0_offset - offset counters + * @param t0_len - size of t0_offset + * @param t1_offset - offset counters + * @param t1_len - size of t1_offset + * @param final - final block flag + * @param result - the result of the compression + * @param result_len - size of result + * @return -1 if there is an error otherwise 0 + */ + int32_t blake2_f( uint32_t rounds, const char* state, uint32_t state_len, const char* msg, uint32_t msg_len, + const char* t0_offset, uint32_t t0_len, const char* t1_offset, uint32_t t1_len, int32_t final, char* result, uint32_t result_len) { + return internal_use_do_not_use::blake2_f( rounds, state, state_len, msg, msg_len, t0_offset, t0_len, t1_offset, t1_len, final, result, result_len); + } + + /** + * Hashes `data` using `sha3` + * + * @param data - data you want to hash + * @param length - size of data + * @param keccak - whether to use `keccak` or NIST variant; keccak = 1 and NIST == 0 + * @return eosio::checksum256 - Computed digest + * + */ + + /** + * Hashes `data` using SHA3 NIST. + * + * @ingroup crypto + * @param data - Data you want to hash + * @param length - Data length + * @return eosio::checksum256 - Computed digest + */ + inline eosio::checksum256 sha3(const char* data, uint32_t length) { + return internal_use_do_not_use::sha3_helper(data, length, false); + } + + /** + * Tests if the SHA3 hash generated from data matches the provided digest. + * + * @ingroup crypto + * @param data - Data you want to hash + * @param length - Data length + * @param hash - digest to compare to + * @note !This method is not optimized away during replay + */ + inline void assert_sha3(const char* data, uint32_t length, const eosio::checksum256& hash) { + const auto& res = internal_use_do_not_use::sha3_helper(data, length, false); + check( hash == res, "SHA3 hash of `data` does not match given `hash`"); + } + + /** + * Hashes `data` using SHA3 Keccak. + * + * @ingroup crypto + * @param data - Data you want to hash + * @param length - Data length + * @return eosio::checksum256 - Computed digest + */ + inline eosio::checksum256 keccak(const char* data, uint32_t length) { + return internal_use_do_not_use::sha3_helper(data, length, true); + } + + /** + * Tests if the SHA3 keccak hash generated from data matches the provided digest. + * + * @ingroup crypto + * @param data - Data you want to hash + * @param length - Data length + * @param hash - digest to compare to + * @note !This method is not optimized away during replay + */ + inline void assert_keccak(const char* data, uint32_t length, const eosio::checksum256& hash) { + const auto& res = internal_use_do_not_use::sha3_helper(data, length, true); + check( hash == res, "Keccak hash of `data` does not match given `hash`"); + } + + /** + * Calculates the uncompressed public key used for a given signature on a given digest. + * + * @ingroup crypto + * @param sig - signature. + * @param sig_len - size of signature + * @param dig - digest of the message that was signed. + * @param dig_len - size of digest + * @param pub - public key result + * @param pub_len - size of public key result + * + * @return -1 if there was an error 0 otherwise. + */ + inline int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len ) { + return internal_use_do_not_use::k1_recover( sig, sig_len, dig, dig_len, pub, pub_len ); + } +} diff --git a/libraries/eosiolib/crypto.cpp b/libraries/eosiolib/crypto.cpp index a4835c2feb..bc96fbd0db 100644 --- a/libraries/eosiolib/crypto.cpp +++ b/libraries/eosiolib/crypto.cpp @@ -39,27 +39,9 @@ extern "C" { int recover_key( const capi_checksum256* digest, const char* sig, size_t siglen, char* pub, size_t publen ); - __attribute__((eosio_wasm_import)) - int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len); - __attribute__((eosio_wasm_import)) void assert_recover_key( const capi_checksum256* digest, const char* sig, size_t siglen, const char* pub, size_t publen ); - - __attribute__((eosio_wasm_import)) - void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, int32_t keccak ); - - __attribute__((eosio_wasm_import)) - int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len); - - __attribute__((eosio_wasm_import)) - int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len); - - __attribute__((eosio_wasm_import)) - int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len); - - __attribute__((eosio_wasm_import)) - int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len); } namespace eosio { @@ -84,33 +66,6 @@ namespace eosio { ::assert_ripemd160( data, length, reinterpret_cast(hash_data.data()) ); } - static inline auto sha3_helper(const char* data, uint32_t length, bool keccak) { - ::capi_checksum256 hash; - ::sha3( data, length, (char*)&hash, sizeof(hash), keccak); - eosio::checksum256 dg; - eosio::datastream ds = {&hash.hash[0], sizeof(hash)}; - ds >> dg; - return dg; - } - - eosio::checksum256 keccak(const char* data, uint32_t length) { - return sha3_helper(data, length, true); - } - - eosio::checksum256 sha3(const char* data, uint32_t length) { - return sha3_helper(data, length, false); - } - - void assert_sha3(const char* data, uint32_t length, const eosio::checksum256& hash) { - const auto& res = sha3_helper(data, length, false); - check( hash == res, "SHA3 hash of `data` does not match given `hash`"); - } - - void assert_keccak(const char* data, uint32_t length, const eosio::checksum256& hash) { - const auto& res = sha3_helper(data, length, true); - check( hash == res, "Keccak hash of `data` does not match given `hash`"); - } - eosio::checksum256 sha256( const char* data, uint32_t length ) { ::capi_checksum256 hash; ::sha256( data, length, &hash ); @@ -176,4 +131,4 @@ namespace eosio { sig_data.data(), sig_data.size(), pubkey_data.data(), pubkey_data.size() ); } -} \ No newline at end of file +} diff --git a/libraries/native/native/eosio/intrinsics_def.hpp b/libraries/native/native/eosio/intrinsics_def.hpp index 6a5c5743df..fc5ee04a45 100644 --- a/libraries/native/native/eosio/intrinsics_def.hpp +++ b/libraries/native/native/eosio/intrinsics_def.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include From aa0595718d1874e7641b6cb6e13db230272cdba4 Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Thu, 25 Aug 2022 16:16:55 -0400 Subject: [PATCH 2/2] add #include to crypto_primitives_tests.cpp --- tests/unit/test_contracts/crypto_primitives_tests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_contracts/crypto_primitives_tests.cpp b/tests/unit/test_contracts/crypto_primitives_tests.cpp index f5ccd2c8a8..92d887f497 100644 --- a/tests/unit/test_contracts/crypto_primitives_tests.cpp +++ b/tests/unit/test_contracts/crypto_primitives_tests.cpp @@ -1,5 +1,6 @@ #include #include +#include using namespace eosio; @@ -23,4 +24,4 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ eosio::assert_keccak(val.c_str(), val.size(), sha3_dg); } -}; \ No newline at end of file +};