libswarm-ng

C implementation of BMT hasher, Swarmhash and Single Owner Chunk for swarm
git clone git://git.defalsify.org/libswarm-ng.git
Log | Files | Refs | Submodules | README

commit c749ff1ece8690bfe11b12c70db821ee7d065d4e
parent d1926b628743376ea13ae8fac5102df53e1298ab
Author: nolash <dev@holbrook.no>
Date:   Tue, 14 Sep 2021 12:58:41 +0200

Add next level hasher

Diffstat:
Msrc/bmt.c | 28++++++++++++++--------------
Msrc/bmt.h | 12++++++------
Msrc/file.c | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/file.h | 15+++++++++------
Mtest/check_file.c | 12+++++++-----
5 files changed, 96 insertions(+), 36 deletions(-)

diff --git a/src/bmt.c b/src/bmt.c @@ -5,26 +5,26 @@ #include "bmt.h" -#define _DIGEST_INPUT_SIZE _WORD_SIZE*2 -#define _ROLLUP_TARGET BLOCK_SIZE + _DATA_LENGTH_TYPESIZE + _WORD_SIZE +#define _SWARM_DIGEST_INPUT_SIZE _SWARM_WORD_SIZE*2 +#define _SWARM_ROLLUP_TARGET SWARM_BLOCK_SIZE + _SWARM_DATA_LENGTH_TYPESIZE + _SWARM_WORD_SIZE #define _KECCAK_RATE 200-64 #define _KECCAK_PADDING 0x01 static int bmt_rollup(bmt_t *bmt_content) { - char *last_target = bmt_content->w_ptr + _WORD_SIZE; + char *last_target = bmt_content->w_ptr + _SWARM_WORD_SIZE; char *start = bmt_content->w_ptr; char buf[256]; int r; while (last_target != 0x00) { while (bmt_content->r_ptr < bmt_content->target) { - r = keccak_hash((unsigned char*)buf, _WORD_SIZE, (unsigned char*)bmt_content->r_ptr, _DIGEST_INPUT_SIZE, _KECCAK_RATE, _KECCAK_PADDING); + r = keccak_hash((unsigned char*)buf, _SWARM_WORD_SIZE, (unsigned char*)bmt_content->r_ptr, _SWARM_DIGEST_INPUT_SIZE, _KECCAK_RATE, _KECCAK_PADDING); if (r != 0) { return 1; } - memcpy(bmt_content->w_ptr, buf, _WORD_SIZE); - bmt_content->w_ptr += _WORD_SIZE; - bmt_content->r_ptr += _DIGEST_INPUT_SIZE; + memcpy(bmt_content->w_ptr, buf, _SWARM_WORD_SIZE); + bmt_content->w_ptr += _SWARM_WORD_SIZE; + bmt_content->r_ptr += _SWARM_DIGEST_INPUT_SIZE; } bmt_content->target = start + ((bmt_content->target - start) / 2); if (bmt_content->target == last_target) { @@ -34,24 +34,24 @@ static int bmt_rollup(bmt_t *bmt_content) { bmt_content->w_ptr = start; } - r = keccak_hash((unsigned char*)buf, _WORD_SIZE, (unsigned char*)bmt_content->buf, _DATA_LENGTH_TYPESIZE + _WORD_SIZE, _KECCAK_RATE, _KECCAK_PADDING); + r = keccak_hash((unsigned char*)buf, _SWARM_WORD_SIZE, (unsigned char*)bmt_content->buf, _SWARM_DATA_LENGTH_TYPESIZE + _SWARM_WORD_SIZE, _KECCAK_RATE, _KECCAK_PADDING); if (r != 0) { return 1; } - memcpy(bmt_content->buf, buf, _WORD_SIZE); + memcpy(bmt_content->buf, buf, _SWARM_WORD_SIZE); return 0; } -void bmt_init(bmt_t *bmt_content, char *input, size_t input_length, long long data_length) { - bmt_content->w_ptr = (char*)bmt_content->buf+_DATA_LENGTH_TYPESIZE; +void bmt_init(bmt_t *bmt_content, const char *input, const size_t input_length, const long long data_length) { + bmt_content->w_ptr = (char*)bmt_content->buf+_SWARM_DATA_LENGTH_TYPESIZE; bmt_content->r_ptr = bmt_content->w_ptr; - bmt_content->target = bmt_content->w_ptr + BLOCK_SIZE; + bmt_content->target = bmt_content->w_ptr + SWARM_BLOCK_SIZE; - memset(bmt_content->buf, 0, _DATA_LENGTH_TYPESIZE + BLOCK_SIZE); + memset(bmt_content->buf, 0, _SWARM_DATA_LENGTH_TYPESIZE + SWARM_BLOCK_SIZE); memcpy((char*)bmt_content->buf, &data_length, sizeof(long long)); - to_endian(CONVERT_LITTLEENDIAN, _DATA_LENGTH_TYPESIZE, (unsigned char*)bmt_content->buf); + to_endian(CONVERT_LITTLEENDIAN, _SWARM_DATA_LENGTH_TYPESIZE, (unsigned char*)bmt_content->buf); memcpy(bmt_content->w_ptr, input, input_length); } diff --git a/src/bmt.h b/src/bmt.h @@ -1,18 +1,18 @@ #ifndef _LIBSWARM_BMT #define _LIBSWARM_BMT -#define BLOCK_SIZE 4096 -#define _WORD_SIZE 32 -#define _DATA_LENGTH_TYPESIZE 8 +#define SWARM_BLOCK_SIZE 4096 +#define _SWARM_WORD_SIZE 32 +#define _SWARM_DATA_LENGTH_TYPESIZE 8 typedef struct bmt { - char buf[_DATA_LENGTH_TYPESIZE + BLOCK_SIZE]; + char buf[_SWARM_DATA_LENGTH_TYPESIZE + SWARM_BLOCK_SIZE]; char *w_ptr; char *r_ptr; char *target; } bmt_t; -void bmt_init(bmt_t *bmt_content, char *input, size_t input_length, long long data_length); -int bmt_sum(bmt_t *bmt_content); +void bmt_init(bmt_t *bmt_context, const char *input, const size_t input_length, const long long data_length); +int bmt_sum(bmt_t *bmt_context); #endif // _LIBSWARM_BMT diff --git a/src/file.c b/src/file.c @@ -1,15 +1,70 @@ #include <stddef.h> +#include <string.h> #include "file.h" -int filehash_init(filehash_t *filehash_context) { +void filehash_reset(filehash_t *fctx) { int i; + for (i = 0; i < SWARM_LEVELS; i++) { + fctx->ptr[i] = fctx->buf; + fctx->writes[i] = 0; + } + fctx->length = 0; +} + +void filehash_init(filehash_t *fctx) { + int i; + int l; + + l = SWARM_BLOCK_SIZE; for (i = 0; i < SWARM_LEVELS; i++) { - filehash_context->ptr[i] = filehash_context->buf; + fctx->spans[i] = l; + l *= _SWARM_BATCH_SIZE; + } + + filehash_reset(fctx); +} + +static int filehash_write_hash(filehash_t *fctx, int level, const char *data) { + bmt_t *bctx; + int next_level; + int r; + + + fctx->writes[level] += 1; + memcpy(fctx->ptr[level], data, _SWARM_WORD_SIZE); + if (fctx->writes[level] == _SWARM_BATCH_SIZE) { + bctx = &fctx->bmt_context; + next_level = level + 1; + bmt_init(bctx, fctx->ptr[next_level], SWARM_BLOCK_SIZE, (long long)fctx->spans[next_level]); + r = bmt_sum(bctx); + if (r != 0) { + return -1; + } + filehash_write_hash(fctx, level + 1, bctx->buf); + } else { + fctx->ptr[level] += _SWARM_WORD_SIZE; } - filehash_context->length = 0; - filehash_context->writes = 0; - return 0; } + +int filehash_write(filehash_t *fctx, const char *data, const size_t data_length) { + bmt_t *bctx; + int r; + + bctx = &fctx->bmt_context; + + bmt_init(bctx, data, data_length, (long long)data_length); + r = bmt_sum(bctx); + if (r != 0) { + return -1; + } + r = filehash_write_hash(fctx, 0, bctx->buf); + if (r != 0) { + return -1; + } + fctx->length += data_length; + + return data_length; +} diff --git a/src/file.h b/src/file.h @@ -3,18 +3,21 @@ #include "bmt.h" -#define SWARM_BATCH_SIZE (int)(BLOCK_SIZE / _WORD_SIZE) +#define _SWARM_BATCH_SIZE (int)(SWARM_BLOCK_SIZE / _SWARM_WORD_SIZE) #define SWARM_LEVELS 9 typedef struct filehash { - char buf[SWARM_LEVELS][BLOCK_SIZE]; + char buf[SWARM_LEVELS * SWARM_BLOCK_SIZE]; char *ptr[SWARM_LEVELS]; - long long byte_length; - long long writes; + long long writes[SWARM_LEVELS]; + long long spans[SWARM_LEVELS]; + long long length; + bmt_t bmt_context; } filehash_t; -int filehash_init(filehash_t *filehash_context); -int filehash_write(filehash_t *filehash_context, char *data, size_t data_length); +void filehash_reset(filehash_t *filehash_context); +void filehash_init(filehash_t *filehash_context); +int filehash_write(filehash_t *filehash_context, const char *data, const size_t data_length); int filehash_sum(filehash_t *filehash_content); #endif // _LIBSWARM_FILE diff --git a/test/check_file.c b/test/check_file.c @@ -6,15 +6,15 @@ START_TEST(check_file_init) { - ck_assert_int_eq(SWARM_BATCH_SIZE, 128); + ck_assert_int_eq(_SWARM_BATCH_SIZE, 128); filehash_t fh; int r; - r = filehash_init(&fh); + filehash_init(&fh); - ck_assert_int_eq(r, 0); ck_assert_ptr_eq(fh.ptr[SWARM_LEVELS-1], fh.buf); + ck_assert_int_eq(fh.spans[1], _SWARM_BATCH_SIZE * SWARM_BLOCK_SIZE); } END_TEST @@ -22,12 +22,14 @@ START_TEST(check_file_single_write) { filehash_t fh; int r; - char *data = "foo"; - + const char *data = "foo"; filehash_init(&fh); r = filehash_write(&fh, data, strlen(data)); + ck_assert_int_eq(r, 3); + ck_assert_int_eq(fh.writes[0], 1); + ck_assert_int_eq(fh.length, 3); } END_TEST