UNPKG

@aggris2/ssz

Version:

Simple Serialize

81 lines 2.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.nextPowerOf2 = exports.maxChunksToDepth = exports.bitLength = exports.mixInLength = exports.splitIntoRootChunks = exports.merkleize = exports.hash64 = void 0; const as_sha256_1 = require("@chainsafe/as-sha256"); const zeros_1 = require("./zeros"); function hash64(bytes32A, bytes32B) { return as_sha256_1.digest2Bytes32(bytes32A, bytes32B); } exports.hash64 = hash64; function merkleize(chunks, padFor) { const layerCount = bitLength(nextPowerOf2(padFor) - 1); if (chunks.length == 0) { return zeros_1.zeroHash(layerCount); } let chunkCount = chunks.length; // Instead of pushing on all padding zero chunks at the leaf level // we push on zero hash chunks at the highest possible level to avoid over-hashing for (let l = 0; l < layerCount; l++) { const padCount = chunkCount % 2; const paddedChunkCount = chunkCount + padCount; // if the chunks.length is odd // we need to push on the zero-hash of that level to merkleize that level for (let i = 0; i < padCount; i++) { chunks[chunkCount + i] = zeros_1.zeroHash(l); } for (let i = 0; i < paddedChunkCount; i += 2) { chunks[i / 2] = hash64(chunks[i], chunks[i + 1]); } chunkCount = paddedChunkCount / 2; } return chunks[0]; } exports.merkleize = merkleize; /** * Split a long Uint8Array into Uint8Array of exactly 32 bytes */ function splitIntoRootChunks(longChunk) { const chunkCount = Math.ceil(longChunk.length / 32); const chunks = new Array(chunkCount); for (let i = 0; i < chunkCount; i++) { const chunk = new Uint8Array(32); chunk.set(longChunk.slice(i * 32, (i + 1) * 32)); chunks[i] = chunk; } return chunks; } exports.splitIntoRootChunks = splitIntoRootChunks; /** @ignore */ function mixInLength(root, length) { const lengthBuf = Buffer.alloc(32); lengthBuf.writeUIntLE(length, 0, 6); return hash64(root, lengthBuf); } exports.mixInLength = mixInLength; // x2 faster than bitLengthStr() which uses Number.toString(2) function bitLength(i) { if (i === 0) { return 0; } return Math.floor(Math.log2(i)) + 1; } exports.bitLength = bitLength; /** * Given maxChunkCount return the chunkDepth * ``` * n: [0,1,2,3,4,5,6,7,8,9] * d: [0,0,1,2,2,3,3,3,3,4] * ``` */ function maxChunksToDepth(n) { if (n === 0) return 0; return Math.ceil(Math.log2(n)); } exports.maxChunksToDepth = maxChunksToDepth; /** @ignore */ function nextPowerOf2(n) { return n <= 0 ? 1 : Math.pow(2, bitLength(n - 1)); } exports.nextPowerOf2 = nextPowerOf2; //# sourceMappingURL=merkleize.js.map