biketrack-app/node_modules/@ethersphere/bee-js/dist/mjs/chunk/bmt.js

56 lines
1.8 KiB
JavaScript
Raw Normal View History

2022-07-11 10:27:11 +02:00
// For ESM compatibility
import pkg from 'js-sha3';
const {
keccak256
} = pkg;
import { BeeArgumentError } from "../utils/error.js";
import { keccak256Hash } from "../utils/hash.js";
const MAX_CHUNK_PAYLOAD_SIZE = 4096;
const SEGMENT_SIZE = 32;
const SEGMENT_PAIR_SIZE = 2 * SEGMENT_SIZE;
const HASH_SIZE = 32;
/**
* Calculate a Binary Merkle Tree hash for a chunk
*
* The BMT chunk address is the hash of the 8 byte span and the root
* hash of a binary Merkle tree (BMT) built on the 32-byte segments
* of the underlying data.
*
* If the chunk content is less than 4k, the hash is calculated as
* if the chunk was padded with all zeros up to 4096 bytes.
*
* @param chunkContent Chunk data including span and payload as well
*
* @returns the keccak256 hash in a byte array
*/
export function bmtHash(chunkContent) {
const span = chunkContent.slice(0, 8);
const payload = chunkContent.slice(8);
const rootHash = bmtRootHash(payload);
const chunkHashInput = new Uint8Array([...span, ...rootHash]);
const chunkHash = keccak256Hash(chunkHashInput);
return chunkHash;
}
function bmtRootHash(payload) {
if (payload.length > MAX_CHUNK_PAYLOAD_SIZE) {
throw new BeeArgumentError('invalid data length', payload);
} // create an input buffer padded with zeros
let input = new Uint8Array([...payload, ...new Uint8Array(MAX_CHUNK_PAYLOAD_SIZE - payload.length)]);
while (input.length !== HASH_SIZE) {
const output = new Uint8Array(input.length / 2); // in each round we hash the segment pairs together
for (let offset = 0; offset < input.length; offset += SEGMENT_PAIR_SIZE) {
const hashNumbers = keccak256.array(input.slice(offset, offset + SEGMENT_PAIR_SIZE));
output.set(hashNumbers, offset / 2);
}
input = output;
}
return input;
}