153 lines
2.7 KiB
C
153 lines
2.7 KiB
C
//
|
|
// Created by haraldwolff on 08.08.22.
|
|
//
|
|
|
|
#include <merkle.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
|
|
int highest_one(long l){
|
|
long test = 1l<<63;
|
|
|
|
for (int n=63; n>=0 ; n--)
|
|
{
|
|
if (l & test)
|
|
return n;
|
|
test >>= 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int merkle_create(merkle_t **merkle, int n, int minwidth){
|
|
*merkle = malloc(sizeof(merkle_t));
|
|
if (!*merkle)
|
|
return -ENOMEM;
|
|
|
|
memset( *merkle, 0x00, sizeof(merkle_t));
|
|
|
|
int s = merkle_init(*merkle, n, minwidth);
|
|
if (s){
|
|
free(*merkle);
|
|
return s;
|
|
}
|
|
(*merkle)->flags |= MF_ALLOC;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int merkle_init(merkle_t *merkle, int n, int minwidth){
|
|
int l = 0;
|
|
int _width = 1;
|
|
int length = 1;
|
|
|
|
while (_width < minwidth){
|
|
l++;
|
|
_width *= n;
|
|
length += _width;
|
|
}
|
|
|
|
merkle->indeces = malloc(sizeof(int)*(l+1));
|
|
if (!merkle->indeces)
|
|
return -ENOMEM;
|
|
|
|
merkle->hashes = malloc(sizeof(uint64_t)*length);
|
|
if (!merkle->hashes) {
|
|
free(merkle->indeces);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
merkle->parameters.n = n;
|
|
merkle->parameters.depth = l;
|
|
merkle->parameters.width = _width;
|
|
merkle->parameters.length = length;
|
|
|
|
merkle->indeces[0] = 0;
|
|
if (l > 0)
|
|
{
|
|
int i = 1;
|
|
for (int d=1;d<=l;d++){
|
|
merkle->indeces[d] = merkle->indeces[d-1] + i;
|
|
i*=n;
|
|
}
|
|
}
|
|
|
|
memset(merkle->hashes, 0x00, sizeof(uint64_t) * length );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int merkle_free(merkle_t *merkle){
|
|
if (merkle){
|
|
if (merkle->hashes)
|
|
free(merkle->hashes);
|
|
if (merkle->indeces)
|
|
free(merkle->indeces);
|
|
if (merkle->flags & MF_ALLOC)
|
|
free(merkle);
|
|
return 0;
|
|
}
|
|
return -EINVAL;
|
|
}
|
|
|
|
int merkle_get(merkle_t *merkle, int level, int n, uint64_t *hash){
|
|
uint64_t *row;
|
|
int rowlength;
|
|
int s = merkle_get_row(merkle, level, &row, &rowlength);
|
|
if (s < 0)
|
|
return s;
|
|
/*
|
|
for (int i=level;i<merkle->parameters.depth;i++)
|
|
n /= merkle->parameters.n;
|
|
*/
|
|
if (hash)
|
|
*hash = row[n];
|
|
return 0;
|
|
}
|
|
|
|
int merkle_set(merkle_t *merkle, int level, int n, uint64_t hash){
|
|
uint64_t *row;
|
|
int rowlength;
|
|
int s = merkle_get_row(merkle, level, &row, &rowlength);
|
|
if (s < 0)
|
|
return s;
|
|
/*
|
|
for (int i=level;i<merkle->parameters.depth;i++)
|
|
n /= merkle->parameters.n;
|
|
*/
|
|
row[n] = hash;
|
|
return 0;
|
|
}
|
|
|
|
int merkle_get_row(merkle_t *merkle, int level, uint64_t **offset, int *size){
|
|
if (!merkle)
|
|
return -EINVAL;
|
|
if ((level<0) || (level > merkle->parameters.depth))
|
|
return -EINVAL;
|
|
|
|
if (offset)
|
|
*offset = &merkle->hashes[merkle->indeces[level]];
|
|
if (size)
|
|
*size = merkle->indeces[level]+1;
|
|
|
|
return merkle->indeces[level];
|
|
}
|
|
|
|
int merkle_dump(merkle_t *merkle){
|
|
uint64_t *row;
|
|
int rowlength;
|
|
|
|
for (int d=0; d <= merkle->parameters.depth; d++)
|
|
{
|
|
merkle_get_row( merkle, d, &row, &rowlength);
|
|
for (int p=0;( p < rowlength) && (p < 8);p++)
|
|
{
|
|
fprintf(stderr, "0x%016lx ", row[p]);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
}
|
|
return 0;
|
|
}
|