sparse-tools/src/merkle.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;
}