Skip to content

Commit

Permalink
i-u-f version 2.
Browse files Browse the repository at this point in the history
rodiazet committed Oct 29, 2022

Verified

This commit was signed with the committer’s verified signature.
snyk-bot Snyk bot
1 parent c3eb603 commit b35d6bc
Showing 4 changed files with 189 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/ethash/keccak.h
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions include/ethash/keccak.hpp
Original file line number Diff line number Diff line change
@@ -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
104 changes: 104 additions & 0 deletions lib/keccak/keccak.c
Original file line number Diff line number Diff line change
@@ -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;
}
64 changes: 64 additions & 0 deletions test/unittests/test_keccak.cpp
Original file line number Diff line number Diff line change
@@ -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<const uint8_t*>(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;
}
}
}

0 comments on commit b35d6bc

Please sign in to comment.