// // Created by haraldwolff on 08.08.22. // #include #include #include #include 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;iparameters.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=0;iparameters.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]; }