From c3eb60333bbbd00623e3a7e8e61e09a82073203c Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 28 Oct 2022 14:37:31 +0200 Subject: [PATCH 1/3] keccak init-update-final api --- include/ethash/keccak.h | 13 +++ include/ethash/keccak.hpp | 15 ++++ lib/keccak/keccak.c | 151 ++++++++++++++++++++++++++++++++- test/unittests/test_keccak.cpp | 55 ++++++++++++ 4 files changed, 232 insertions(+), 2 deletions(-) diff --git a/include/ethash/keccak.h b/include/ethash/keccak.h index b513b6d0..9d467ca4 100644 --- a/include/ethash/keccak.h +++ b/include/ethash/keccak.h @@ -22,6 +22,19 @@ union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) noexcept; union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) noexcept; union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) noexcept; +struct ethash_keccak256_context { + size_t hash_size; + size_t block_size; + uint64_t state[25]; + uint64_t* state_iter; + uint64_t last_word; + uint8_t* last_word_iter; +}; + +void ethash_keccak256_init(struct ethash_keccak256_context* ctx) noexcept; +void ethash_keccak256_update(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept; +union ethash_hash256 ethash_keccak256_final(struct ethash_keccak256_context* ctx) noexcept; + #ifdef __cplusplus } #endif diff --git a/include/ethash/keccak.hpp b/include/ethash/keccak.hpp index d5dad63b..86ecd9ee 100644 --- a/include/ethash/keccak.hpp +++ b/include/ethash/keccak.hpp @@ -32,4 +32,19 @@ inline hash512 keccak512(const hash512& input) noexcept static constexpr auto keccak256_32 = ethash_keccak256_32; static constexpr auto keccak512_64 = ethash_keccak512_64; +inline void keccak256_init(struct ethash_keccak256_context* ctx) noexcept +{ + ethash_keccak256_init(ctx); +} + +inline void keccak256_update(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept +{ + ethash_keccak256_update(ctx, data, size); +} + +inline hash256 keccak256_final(struct ethash_keccak256_context* ctx) noexcept +{ + return ethash_keccak256_final(ctx); +} + } // namespace ethash diff --git a/lib/keccak/keccak.c b/lib/keccak/keccak.c index 286ea9d3..ec509edf 100644 --- a/lib/keccak/keccak.c +++ b/lib/keccak/keccak.c @@ -44,7 +44,6 @@ static const uint64_t round_constants[24] = { // 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008}; - /// The Keccak-f[1600] function. /// /// The implementation of the Keccak-f function with 1600-bit width of the permutation (b). @@ -342,11 +341,11 @@ static inline ALWAYS_INLINE void keccak( ++data; --size; } + *last_word_iter = 0x01; *state_iter ^= to_le64(last_word); state[(block_size / word_size) - 1] ^= 0x8000000000000000; - keccakf1600_best(state); for (i = 0; i < (hash_size / word_size); ++i) @@ -380,3 +379,151 @@ union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) keccak(hash.word64s, 512, data, 64); return hash; } + +static inline ALWAYS_INLINE void keccak_init(struct ethash_keccak256_context* ctx, size_t bits) +{ + __builtin_memset((uint8_t*)ctx->state, 0, sizeof ctx->state); + ctx->hash_size = bits / 8; + ctx->block_size = (1600 - bits * 2) / 8; + + ctx->last_word = 0; + ctx->last_word_iter = (uint8_t*)&(ctx->last_word); + + ctx->state_iter = ctx->state; +} + +static inline ALWAYS_INLINE void keccak_update( + struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) +{ + static const size_t word_size = sizeof(uint64_t); + size_t i; + + size_t block_size_b = ctx->block_size / word_size; // block size in bytes + size_t last_word_unfilled_size = // calculate unfilled space in last word, ignore if all empty + (word_size - (size_t)(ctx->last_word_iter - (uint8_t*)&(ctx->last_word))) % word_size; + size_t state_unfilled_size = // calculate unfilled space in state, ignore if all empty + (block_size_b - (size_t)(ctx->state_iter - ctx->state)) % block_size_b; + + // fill the last word unfilled space with bytes until it's full + while(last_word_unfilled_size > 0 && size > 0) + { + *ctx->last_word_iter = *data; + ++ctx->last_word_iter; + ++data; + --size; + --last_word_unfilled_size; + } + + // if the last word is full, move it to state. + if(ctx->last_word_iter == (uint8_t*)&(ctx->last_word) + word_size) + { + *ctx->state_iter ^= to_le64(ctx->last_word); + ++ctx->state_iter; + ctx->last_word = 0; + ctx->last_word_iter = (uint8_t*)&(ctx->last_word); + --state_unfilled_size; + } + + // fill the state unfilled space with words until it's full + while(state_unfilled_size > 0 && size >= word_size) + { + *ctx->state_iter ^= load_le(data); + ++ctx->state_iter; + data += word_size; + size -= word_size; + --state_unfilled_size; + } + + // if the state is full, calculate keccak and reset the state iterator + if(ctx->state_iter == ctx->state + (ctx->block_size / word_size)) + { + keccakf1600_best(ctx->state); + ctx->state_iter = ctx->state; + } + + // if there is more data then block size, fill the whole blocks + if(size >= ctx->block_size) + { + while(size >= ctx->block_size) + { + for (i = 0; i < (ctx->block_size / word_size); ++i) + { + ctx->state[i] ^= load_le(data); + data += word_size; + } + + keccakf1600_best(ctx->state); + + size -= ctx->block_size; + } + + ctx->state_iter = ctx->state; + } + + // if there is more data then word size, fill the whole words + while (size >= word_size) + { + *ctx->state_iter ^= load_le(data); + ++ctx->state_iter; + data += word_size; + size -= word_size; + } + + // if there is still some data put it into last word. + while (size > 0) + { + *ctx->last_word_iter = *data; + ++ctx->last_word_iter; + ++data; + --size; + } + + // if the last word is full, move it to state. + if(ctx->last_word_iter == (uint8_t*)&(ctx->last_word) + word_size) + { + *ctx->state_iter ^= to_le64(ctx->last_word); + ++ctx->state_iter; + ctx->last_word = 0; + ctx->last_word_iter = (uint8_t*)&(ctx->last_word); + } + + // if the state is full, calculate keccak and reset the state iterator + if(ctx->state_iter == ctx->state + (ctx->block_size / word_size)) + { + keccakf1600_best(ctx->state); + ctx->state_iter = ctx->state; + } +} + +static inline ALWAYS_INLINE void keccak_final(struct ethash_keccak256_context* ctx, uint64_t* out) +{ + static const size_t word_size = sizeof(uint64_t); + size_t i; + + *ctx->last_word_iter = 0x01; + *ctx->state_iter ^= to_le64(ctx->last_word); + + ctx->state[(ctx->block_size / word_size) - 1] ^= 0x8000000000000000; + + keccakf1600_best(ctx->state); + + for (i = 0; i < (ctx->hash_size / word_size); ++i) + out[i] = to_le64(ctx->state[i]); +} + +void ethash_keccak256_init(struct ethash_keccak256_context* ctx) +{ + keccak_init(ctx, 256); +} + +void ethash_keccak256_update(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) +{ + keccak_update(ctx, data, size); +} + +union ethash_hash256 ethash_keccak256_final(struct ethash_keccak256_context* ctx) +{ + union ethash_hash256 hash; + keccak_final(ctx, hash.word64s); + return hash; +} diff --git a/test/unittests/test_keccak.cpp b/test/unittests/test_keccak.cpp index c4838729..1895911b 100644 --- a/test/unittests/test_keccak.cpp +++ b/test/unittests/test_keccak.cpp @@ -282,3 +282,58 @@ TEST(helpers, to_hash256_empty) hash256 h = to_hash256(hex); EXPECT_EQ(h, hash256{}); } + +TEST(keccak, iuf_test_simple) +{ + const uint8_t* const data = reinterpret_cast(test_text); + + for (auto& t : test_cases) + { + const auto h256 = keccak256(data, t.input_size); + ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; + + struct ethash_keccak256_context ctx; + keccak256_init(&ctx); + keccak256_update(&ctx, data, t.input_size); + const auto h2561 = keccak256_final(&ctx); + ASSERT_EQ(to_hex(h2561), t.expected_hash256) << t.input_size; + + size_t i; + + keccak256_init(&ctx); + for(i = 0; i < t.input_size; ++i) + { + keccak256_update(&ctx, &data[i], 1); + } + const auto h2562 = keccak256_final(&ctx); + ASSERT_EQ(to_hex(h2562), t.expected_hash256) << t.input_size; + + size_t step = 0; + for(step = 1; step < 256; ++step) + { + keccak256_init(&ctx); + + for(i = 0; i < t.input_size; i = i + step) + { + size_t l = t.input_size - i >= step ? step : t.input_size - i; + keccak256_update(&ctx, &data[i], l); + } + const auto h2563 = keccak256_final(&ctx); + ASSERT_EQ(to_hex(h2563), t.expected_hash256) << t.input_size; + } + + + keccak256_init(&ctx); + + i = 0; + while(i < t.input_size) + { + step = (size_t)rand() % 300; + size_t l = t.input_size - i >= step ? step : t.input_size - i; + keccak256_update(&ctx, &data[i], l); + i = i + step; + } + const auto h2563 = keccak256_final(&ctx); + ASSERT_EQ(to_hex(h2563), t.expected_hash256) << t.input_size; + } +} \ No newline at end of file From b35d6bc0951703ccaebac4816a4cdba81684992b Mon Sep 17 00:00:00 2001 From: rodiazet Date: Sat, 29 Oct 2022 15:32:20 +0200 Subject: [PATCH 2/3] i-u-f version 2. --- include/ethash/keccak.h | 6 ++ include/ethash/keccak.hpp | 15 +++++ lib/keccak/keccak.c | 104 +++++++++++++++++++++++++++++++++ test/unittests/test_keccak.cpp | 64 ++++++++++++++++++++ 4 files changed, 189 insertions(+) diff --git a/include/ethash/keccak.h b/include/ethash/keccak.h index 9d467ca4..a5b4f8f3 100644 --- a/include/ethash/keccak.h +++ b/include/ethash/keccak.h @@ -29,12 +29,18 @@ struct ethash_keccak256_context { uint64_t* state_iter; uint64_t last_word; uint8_t* last_word_iter; + uint8_t buffer[136]; + size_t buffer_index; }; void ethash_keccak256_init(struct ethash_keccak256_context* ctx) noexcept; void ethash_keccak256_update(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept; union ethash_hash256 ethash_keccak256_final(struct ethash_keccak256_context* ctx) noexcept; +void ethash_keccak256_init_2(struct ethash_keccak256_context* ctx) noexcept; +void ethash_keccak256_update_2(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept; +union ethash_hash256 ethash_keccak256_final_2(struct ethash_keccak256_context* ctx) noexcept; + #ifdef __cplusplus } #endif diff --git a/include/ethash/keccak.hpp b/include/ethash/keccak.hpp index 86ecd9ee..3bb57995 100644 --- a/include/ethash/keccak.hpp +++ b/include/ethash/keccak.hpp @@ -47,4 +47,19 @@ inline hash256 keccak256_final(struct ethash_keccak256_context* ctx) noexcept return ethash_keccak256_final(ctx); } +inline void keccak256_init_2(struct ethash_keccak256_context* ctx) noexcept +{ + ethash_keccak256_init_2(ctx); +} + +inline void keccak256_update_2(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept +{ + ethash_keccak256_update_2(ctx, data, size); +} + +inline hash256 keccak256_final_2(struct ethash_keccak256_context* ctx) noexcept +{ + return ethash_keccak256_final_2(ctx); +} + } // namespace ethash diff --git a/lib/keccak/keccak.c b/lib/keccak/keccak.c index ec509edf..8f51c1af 100644 --- a/lib/keccak/keccak.c +++ b/lib/keccak/keccak.c @@ -527,3 +527,107 @@ union ethash_hash256 ethash_keccak256_final(struct ethash_keccak256_context* ctx keccak_final(ctx, hash.word64s); return hash; } + +static inline ALWAYS_INLINE void keccak_init_2(struct ethash_keccak256_context* ctx, size_t bits) +{ + __builtin_memset((uint8_t*)ctx->state, 0, sizeof ctx->state); + ctx->state_iter = ctx->state; + + ctx->hash_size = bits / 8; + ctx->block_size = (1600 - bits * 2) / 8; + ctx->last_word = 0; + ctx->last_word_iter = (uint8_t*)&ctx->last_word; + + __builtin_memset(ctx->buffer, 0, sizeof ctx->buffer); + ctx->buffer_index = 0; +} + +static inline ALWAYS_INLINE void keccak_update_2( + struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) +{ + static const size_t word_size = sizeof(uint64_t); + + while(size > 0) + { + size_t empty_space_size = ctx->block_size - ctx->buffer_index; + size_t data_to_load_size = size >= empty_space_size ? empty_space_size : size; + + __builtin_memcpy(&ctx->buffer[ctx->buffer_index], data, data_to_load_size); + ctx->buffer_index += data_to_load_size; + size -= data_to_load_size; + data += data_to_load_size; + + if(ctx->buffer_index == ctx->block_size) + { + size_t i; + uint8_t* d = &ctx->buffer[0]; + + for (i = 0; i < (ctx->block_size / word_size); ++i) + { + *ctx->state_iter ^= load_le(d); + ++ctx->state_iter; + d += word_size; + } + + keccakf1600_best(ctx->state); + ctx->state_iter = ctx->state; + ctx->buffer_index = 0; + } + } +} + +static inline ALWAYS_INLINE void keccak_final_2(struct ethash_keccak256_context* ctx, uint64_t* out) +{ + static const size_t word_size = sizeof(uint64_t); + size_t i; + + if(ctx->buffer_index != 0) + { + uint8_t* d = ctx->buffer; + for (i = 0; i < (ctx->buffer_index / word_size); ++i) + { + *ctx->state_iter ^= load_le(d); + ++ctx->state_iter; + d += word_size; + } + + size_t last_word_size = ctx->buffer_index % word_size; + d = &ctx->buffer[ctx->buffer_index - last_word_size]; + ctx->last_word_iter = (uint8_t*)&ctx->last_word; + + while (last_word_size > 0) + { + *ctx->last_word_iter = *d; + ++ctx->last_word_iter; + ++d; + --last_word_size; + } + } + + *ctx->last_word_iter = 0x01; + *ctx->state_iter ^= to_le64(ctx->last_word); + + ctx->state[(ctx->block_size / word_size) - 1] ^= 0x8000000000000000; + + keccakf1600_best(ctx->state); + + for (i = 0; i < (ctx->hash_size / word_size); ++i) + out[i] = to_le64(ctx->state[i]); +} + +void ethash_keccak256_init_2(struct ethash_keccak256_context* ctx) +{ + keccak_init_2(ctx, 256); +} + +void ethash_keccak256_update_2(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) +{ + keccak_update_2(ctx, data, size); +} + +union ethash_hash256 ethash_keccak256_final_2(struct ethash_keccak256_context* ctx) +{ + union ethash_hash256 hash; + keccak_final_2(ctx, hash.word64s); + return hash; +} diff --git a/test/unittests/test_keccak.cpp b/test/unittests/test_keccak.cpp index 1895911b..8960ce0e 100644 --- a/test/unittests/test_keccak.cpp +++ b/test/unittests/test_keccak.cpp @@ -336,4 +336,68 @@ TEST(keccak, iuf_test_simple) const auto h2563 = keccak256_final(&ctx); ASSERT_EQ(to_hex(h2563), t.expected_hash256) << t.input_size; } +} + +TEST(keccak, iuf_test_simple_2) +{ + const uint8_t* const data = reinterpret_cast(test_text); + + for (auto& t : test_cases) + { + { + struct ethash_keccak256_context ctx; + keccak256_init_2(&ctx); + keccak256_update_2(&ctx, data, t.input_size); + const auto h256 = keccak256_final_2(&ctx); + ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; + } + + { + size_t i; + + struct ethash_keccak256_context ctx; + keccak256_init_2(&ctx); + for(i = 0; i < t.input_size; ++i) + { + keccak256_update_2(&ctx, &data[i], 1); + } + const auto h256 = keccak256_final_2(&ctx); + ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; + } + + { + size_t i; + size_t step = 0; + struct ethash_keccak256_context ctx; + for(step = 1; step < 256; ++step) + { + keccak256_init_2(&ctx); + + for(i = 0; i < t.input_size; i = i + step) + { + size_t l = t.input_size - i >= step ? step : t.input_size - i; + keccak256_update_2(&ctx, &data[i], l); + } + const auto h256 = keccak256_final_2(&ctx); + ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; + } + } + + { + struct ethash_keccak256_context ctx; + keccak256_init_2(&ctx); + + size_t i = 0; + size_t step = 0; + while(i < t.input_size) + { + step = (size_t)rand() % 300; + size_t l = t.input_size - i >= step ? step : t.input_size - i; + keccak256_update_2(&ctx, &data[i], l); + i = i + step; + } + const auto h256 = keccak256_final_2(&ctx); + ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; + } + } } \ No newline at end of file From f061fee9b1c492079d3f3e047e529e72e7d7b21f Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 4 Nov 2022 13:56:16 +0100 Subject: [PATCH 3/3] sanitizers error fixing; corner case bug fixing, --- lib/keccak/keccak.c | 9 +++++---- test/unittests/test_keccak.cpp | 37 +++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/lib/keccak/keccak.c b/lib/keccak/keccak.c index 8f51c1af..a621e665 100644 --- a/lib/keccak/keccak.c +++ b/lib/keccak/keccak.c @@ -8,6 +8,7 @@ #if !__has_builtin(__builtin_memcpy) && !defined(__GNUC__) #include #define __builtin_memcpy memcpy +#define __builtin_memset memset #endif #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ @@ -399,10 +400,10 @@ static inline ALWAYS_INLINE void keccak_update( size_t i; size_t block_size_b = ctx->block_size / word_size; // block size in bytes - size_t last_word_unfilled_size = // calculate unfilled space in last word, ignore if all empty - (word_size - (size_t)(ctx->last_word_iter - (uint8_t*)&(ctx->last_word))) % word_size; - size_t state_unfilled_size = // calculate unfilled space in state, ignore if all empty - (block_size_b - (size_t)(ctx->state_iter - ctx->state)) % block_size_b; + size_t last_word_unfilled_size = // calculate unfilled space in last word + (word_size - (size_t)(ctx->last_word_iter - (uint8_t*)&(ctx->last_word))); + size_t state_unfilled_size = // calculate unfilled space in state + (block_size_b - (size_t)(ctx->state_iter - ctx->state)); // fill the last word unfilled space with bytes until it's full while(last_word_unfilled_size > 0 && size > 0) diff --git a/test/unittests/test_keccak.cpp b/test/unittests/test_keccak.cpp index 8960ce0e..6a69240e 100644 --- a/test/unittests/test_keccak.cpp +++ b/test/unittests/test_keccak.cpp @@ -283,6 +283,25 @@ TEST(helpers, to_hash256_empty) EXPECT_EQ(h, hash256{}); } +static size_t next_data_size_to_load() +{ + static size_t next = 1; + static const size_t sizes[216] + = {225, 50, 73, 72, 285, 273, 139, 299, 193, 243, 43, 102, 294, 262, 209, 114, 88, 94, 179, 233, 248, + 182, 34, 246, 106, 148, 198, 77, 160, 289, 115, 249, 198, 26, 203, 21, 24, 65, 222, 187, 170, 281, + 285, 185, 261, 121, 130, 270, 22, 227, 235, 206, 116, 205, 171, 30, 163, 94, 66, 98, 112, 271, 98, + 91, 181, 181, 145, 290, 12, 261, 183, 82, 40, 25, 40, 164, 293, 150, 96, 195, 218, 122, 240, 99, 7, + 71, 155, 165, 180, 238, 131, 271, 286, 186, 255, 62, 65, 110, 205, 86, 2, 83, 182, 225, 5, 156, 138, + 139, 146, 3, 250, 51, 184, 282, 9, 109, 34, 245, 169, 63, 240, 100, 151, 134, 74, 125, 225, 30, 215, + 199, 275, 131, 128, 89, 37, 195, 286, 220, 117, 183, 32, 132, 51, 122, 244, 104, 59, 73, 45, 188, 115, + 231, 179, 217, 16, 110, 58, 142, 186, 215, 201, 223, 198, 152, 64, 9, 113, 39, 141, 209, 170, 84, 209, + 16, 92, 64, 85, 239, 128, 88, 298, 153, 28, 269, 30, 38, 46, 97, 242, 119, 102, 299, 103, 288, 251, 187, + 192, 8, 57, 293, 221, 43, 184, 207, 50, 129, 203, 45, 139, 0, 129, 82, 285, 254, 214, 213}; + + next = (next + 1) % 216; + return sizes[next]; +} + TEST(keccak, iuf_test_simple) { const uint8_t* const data = reinterpret_cast(test_text); @@ -292,7 +311,7 @@ TEST(keccak, iuf_test_simple) const auto h256 = keccak256(data, t.input_size); ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; - struct ethash_keccak256_context ctx; + struct ethash_keccak256_context ctx = {}; keccak256_init(&ctx); keccak256_update(&ctx, data, t.input_size); const auto h2561 = keccak256_final(&ctx); @@ -328,11 +347,11 @@ TEST(keccak, iuf_test_simple) i = 0; while(i < t.input_size) { - step = (size_t)rand() % 300; + step = next_data_size_to_load(); size_t l = t.input_size - i >= step ? step : t.input_size - i; keccak256_update(&ctx, &data[i], l); i = i + step; - } + } const auto h2563 = keccak256_final(&ctx); ASSERT_EQ(to_hex(h2563), t.expected_hash256) << t.input_size; } @@ -345,7 +364,7 @@ TEST(keccak, iuf_test_simple_2) for (auto& t : test_cases) { { - struct ethash_keccak256_context ctx; + struct ethash_keccak256_context ctx = {}; keccak256_init_2(&ctx); keccak256_update_2(&ctx, data, t.input_size); const auto h256 = keccak256_final_2(&ctx); @@ -355,7 +374,7 @@ TEST(keccak, iuf_test_simple_2) { size_t i; - struct ethash_keccak256_context ctx; + struct ethash_keccak256_context ctx = {}; keccak256_init_2(&ctx); for(i = 0; i < t.input_size; ++i) { @@ -368,7 +387,7 @@ TEST(keccak, iuf_test_simple_2) { size_t i; size_t step = 0; - struct ethash_keccak256_context ctx; + struct ethash_keccak256_context ctx = {}; for(step = 1; step < 256; ++step) { keccak256_init_2(&ctx); @@ -384,14 +403,14 @@ TEST(keccak, iuf_test_simple_2) } { - struct ethash_keccak256_context ctx; + struct ethash_keccak256_context ctx = {}; keccak256_init_2(&ctx); size_t i = 0; size_t step = 0; while(i < t.input_size) { - step = (size_t)rand() % 300; + step = next_data_size_to_load(); size_t l = t.input_size - i >= step ? step : t.input_size - i; keccak256_update_2(&ctx, &data[i], l); i = i + step; @@ -400,4 +419,4 @@ TEST(keccak, iuf_test_simple_2) ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size; } } -} \ No newline at end of file +}