Skip to content
This repository was archived by the owner on Jun 8, 2025. It is now read-only.

Commit b35d6bc

Browse files
committed
i-u-f version 2.
1 parent c3eb603 commit b35d6bc

4 files changed

Lines changed: 189 additions & 0 deletions

File tree

include/ethash/keccak.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ struct ethash_keccak256_context {
2929
uint64_t* state_iter;
3030
uint64_t last_word;
3131
uint8_t* last_word_iter;
32+
uint8_t buffer[136];
33+
size_t buffer_index;
3234
};
3335

3436
void ethash_keccak256_init(struct ethash_keccak256_context* ctx) noexcept;
3537
void ethash_keccak256_update(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept;
3638
union ethash_hash256 ethash_keccak256_final(struct ethash_keccak256_context* ctx) noexcept;
3739

40+
void ethash_keccak256_init_2(struct ethash_keccak256_context* ctx) noexcept;
41+
void ethash_keccak256_update_2(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept;
42+
union ethash_hash256 ethash_keccak256_final_2(struct ethash_keccak256_context* ctx) noexcept;
43+
3844
#ifdef __cplusplus
3945
}
4046
#endif

include/ethash/keccak.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,19 @@ inline hash256 keccak256_final(struct ethash_keccak256_context* ctx) noexcept
4747
return ethash_keccak256_final(ctx);
4848
}
4949

50+
inline void keccak256_init_2(struct ethash_keccak256_context* ctx) noexcept
51+
{
52+
ethash_keccak256_init_2(ctx);
53+
}
54+
55+
inline void keccak256_update_2(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size) noexcept
56+
{
57+
ethash_keccak256_update_2(ctx, data, size);
58+
}
59+
60+
inline hash256 keccak256_final_2(struct ethash_keccak256_context* ctx) noexcept
61+
{
62+
return ethash_keccak256_final_2(ctx);
63+
}
64+
5065
} // namespace ethash

lib/keccak/keccak.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,3 +527,107 @@ union ethash_hash256 ethash_keccak256_final(struct ethash_keccak256_context* ctx
527527
keccak_final(ctx, hash.word64s);
528528
return hash;
529529
}
530+
531+
static inline ALWAYS_INLINE void keccak_init_2(struct ethash_keccak256_context* ctx, size_t bits)
532+
{
533+
__builtin_memset((uint8_t*)ctx->state, 0, sizeof ctx->state);
534+
ctx->state_iter = ctx->state;
535+
536+
ctx->hash_size = bits / 8;
537+
ctx->block_size = (1600 - bits * 2) / 8;
538+
ctx->last_word = 0;
539+
ctx->last_word_iter = (uint8_t*)&ctx->last_word;
540+
541+
__builtin_memset(ctx->buffer, 0, sizeof ctx->buffer);
542+
ctx->buffer_index = 0;
543+
}
544+
545+
static inline ALWAYS_INLINE void keccak_update_2(
546+
struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size)
547+
{
548+
static const size_t word_size = sizeof(uint64_t);
549+
550+
while(size > 0)
551+
{
552+
size_t empty_space_size = ctx->block_size - ctx->buffer_index;
553+
size_t data_to_load_size = size >= empty_space_size ? empty_space_size : size;
554+
555+
__builtin_memcpy(&ctx->buffer[ctx->buffer_index], data, data_to_load_size);
556+
ctx->buffer_index += data_to_load_size;
557+
size -= data_to_load_size;
558+
data += data_to_load_size;
559+
560+
if(ctx->buffer_index == ctx->block_size)
561+
{
562+
size_t i;
563+
uint8_t* d = &ctx->buffer[0];
564+
565+
for (i = 0; i < (ctx->block_size / word_size); ++i)
566+
{
567+
*ctx->state_iter ^= load_le(d);
568+
++ctx->state_iter;
569+
d += word_size;
570+
}
571+
572+
keccakf1600_best(ctx->state);
573+
ctx->state_iter = ctx->state;
574+
ctx->buffer_index = 0;
575+
}
576+
}
577+
}
578+
579+
static inline ALWAYS_INLINE void keccak_final_2(struct ethash_keccak256_context* ctx, uint64_t* out)
580+
{
581+
static const size_t word_size = sizeof(uint64_t);
582+
size_t i;
583+
584+
if(ctx->buffer_index != 0)
585+
{
586+
uint8_t* d = ctx->buffer;
587+
for (i = 0; i < (ctx->buffer_index / word_size); ++i)
588+
{
589+
*ctx->state_iter ^= load_le(d);
590+
++ctx->state_iter;
591+
d += word_size;
592+
}
593+
594+
size_t last_word_size = ctx->buffer_index % word_size;
595+
d = &ctx->buffer[ctx->buffer_index - last_word_size];
596+
ctx->last_word_iter = (uint8_t*)&ctx->last_word;
597+
598+
while (last_word_size > 0)
599+
{
600+
*ctx->last_word_iter = *d;
601+
++ctx->last_word_iter;
602+
++d;
603+
--last_word_size;
604+
}
605+
}
606+
607+
*ctx->last_word_iter = 0x01;
608+
*ctx->state_iter ^= to_le64(ctx->last_word);
609+
610+
ctx->state[(ctx->block_size / word_size) - 1] ^= 0x8000000000000000;
611+
612+
keccakf1600_best(ctx->state);
613+
614+
for (i = 0; i < (ctx->hash_size / word_size); ++i)
615+
out[i] = to_le64(ctx->state[i]);
616+
}
617+
618+
void ethash_keccak256_init_2(struct ethash_keccak256_context* ctx)
619+
{
620+
keccak_init_2(ctx, 256);
621+
}
622+
623+
void ethash_keccak256_update_2(struct ethash_keccak256_context* ctx, const uint8_t* data, size_t size)
624+
{
625+
keccak_update_2(ctx, data, size);
626+
}
627+
628+
union ethash_hash256 ethash_keccak256_final_2(struct ethash_keccak256_context* ctx)
629+
{
630+
union ethash_hash256 hash;
631+
keccak_final_2(ctx, hash.word64s);
632+
return hash;
633+
}

test/unittests/test_keccak.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,4 +336,68 @@ TEST(keccak, iuf_test_simple)
336336
const auto h2563 = keccak256_final(&ctx);
337337
ASSERT_EQ(to_hex(h2563), t.expected_hash256) << t.input_size;
338338
}
339+
}
340+
341+
TEST(keccak, iuf_test_simple_2)
342+
{
343+
const uint8_t* const data = reinterpret_cast<const uint8_t*>(test_text);
344+
345+
for (auto& t : test_cases)
346+
{
347+
{
348+
struct ethash_keccak256_context ctx;
349+
keccak256_init_2(&ctx);
350+
keccak256_update_2(&ctx, data, t.input_size);
351+
const auto h256 = keccak256_final_2(&ctx);
352+
ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size;
353+
}
354+
355+
{
356+
size_t i;
357+
358+
struct ethash_keccak256_context ctx;
359+
keccak256_init_2(&ctx);
360+
for(i = 0; i < t.input_size; ++i)
361+
{
362+
keccak256_update_2(&ctx, &data[i], 1);
363+
}
364+
const auto h256 = keccak256_final_2(&ctx);
365+
ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size;
366+
}
367+
368+
{
369+
size_t i;
370+
size_t step = 0;
371+
struct ethash_keccak256_context ctx;
372+
for(step = 1; step < 256; ++step)
373+
{
374+
keccak256_init_2(&ctx);
375+
376+
for(i = 0; i < t.input_size; i = i + step)
377+
{
378+
size_t l = t.input_size - i >= step ? step : t.input_size - i;
379+
keccak256_update_2(&ctx, &data[i], l);
380+
}
381+
const auto h256 = keccak256_final_2(&ctx);
382+
ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size;
383+
}
384+
}
385+
386+
{
387+
struct ethash_keccak256_context ctx;
388+
keccak256_init_2(&ctx);
389+
390+
size_t i = 0;
391+
size_t step = 0;
392+
while(i < t.input_size)
393+
{
394+
step = (size_t)rand() % 300;
395+
size_t l = t.input_size - i >= step ? step : t.input_size - i;
396+
keccak256_update_2(&ctx, &data[i], l);
397+
i = i + step;
398+
}
399+
const auto h256 = keccak256_final_2(&ctx);
400+
ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size;
401+
}
402+
}
339403
}

0 commit comments

Comments
 (0)