@iden3/js-merkletree
Version:
javascript sparse merkle tree library
103 lines (102 loc) • 3.16 kB
JavaScript
import { HASH_BYTES_LENGTH } from '../../constants';
import { bytesEqual, swapEndianness, bytes2Hex, bytes2BinaryString, checkBigIntInField, bigIntToUINT8Array } from '../utils';
import { Hex, poseidon } from '@iden3/js-crypto';
export class Hash {
constructor(_bytes) {
if (_bytes?.length) {
if (_bytes.length !== HASH_BYTES_LENGTH) {
throw new Error(`Expected ${HASH_BYTES_LENGTH} bytes, found ${_bytes.length} bytes`);
}
this.bytes = _bytes;
}
else {
this.bytes = new Uint8Array(HASH_BYTES_LENGTH);
}
}
// returns a new copy, in little endian
get value() {
return this.bytes;
}
// bytes should be in big-endian
set value(bytes) {
if (bytes.length !== HASH_BYTES_LENGTH) {
throw `Expected 32 bytes, found ${bytes.length} bytes`;
}
this.bytes = swapEndianness(bytes);
}
string() {
return this.bigInt().toString(10);
}
hex() {
return bytes2Hex(this.bytes);
}
equals(hash) {
return bytesEqual(this.value, hash.value);
}
bigInt() {
const bytes = swapEndianness(this.value);
return BigInt(bytes2BinaryString(bytes));
}
static fromString(s) {
try {
return Hash.fromBigInt(BigInt(s));
}
catch (e) {
const deserializedHash = JSON.parse(s);
const bytes = Uint8Array.from(Object.values(deserializedHash.bytes));
return new Hash(bytes);
}
}
static fromBigInt(i) {
if (!checkBigIntInField(i)) {
throw new Error('NewBigIntFromHashBytes: Value not inside the Finite Field');
}
const bytes = bigIntToUINT8Array(i);
return new Hash(swapEndianness(bytes));
}
static fromHex(h) {
if (!h) {
return ZERO_HASH;
}
return new Hash(Hex.decodeString(h));
}
toJSON() {
return this.string();
}
}
export const ZERO_HASH = new Hash();
/**
* @deprecated The method should not be used and will be removed in the next major version,
* please use Hash.fromBigInt instead
*/
export const newHashFromBigInt = (bigNum) => {
return Hash.fromBigInt(bigNum);
};
/**
* @deprecated The method should not be used and will be removed in the next major version,
* please use Hash.fromBigInt instead
*/
export const newHashFromHex = (h) => {
return Hash.fromHex(h);
};
/**
* @deprecated The method should not be used and will be removed in the next major version,
* please use Hash.fromBigString instead
*/
export const newHashFromString = (decimalString) => {
return Hash.fromString(decimalString);
};
export const hashElems = (e) => {
const hashBigInt = poseidon.hash(e);
return Hash.fromBigInt(hashBigInt);
};
export const hashElemsKey = (k, e) => {
const hashBigInt = poseidon.hash([...e, k]);
return Hash.fromBigInt(hashBigInt);
};
export const circomSiblingsFromSiblings = (siblings, levels) => {
for (let i = siblings.length; i < levels; i += 1) {
siblings.push(ZERO_HASH);
}
return siblings;
};