From b35d6bc0951703ccaebac4816a4cdba81684992b Mon Sep 17 00:00:00 2001 From: rodiazet Date: Sat, 29 Oct 2022 15:32:20 +0200 Subject: [PATCH] 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