UNPKG

@chainsafe/ssz

Version:
128 lines 4.77 kB
import { concatGindices, getHashComputations, toGindex, } from "@chainsafe/persistent-merkle-tree"; import { byteArrayEquals, fromHexString, slice, toHexString } from "../util/byteArray.js"; import { CompositeType, LENGTH_GINDEX } from "./composite.js"; /** * ByteArray: ordered array collection of byte values * - Value: `Uint8Array` * - View: `Uint8Array` * - ViewDU: `Uint8Array` * * ByteArray is an immutable value which is represented by a Uint8Array for memory efficiency and performance. * Note: Consumers of this type MUST never mutate the `Uint8Array` representation of a ByteArray. */ export class ByteArrayType extends CompositeType { isViewMutable = false; defaultValue() { // Since it's a byte array the minSize is bytes is the default size return new Uint8Array(this.minSize); } getView(tree) { return this.getViewDU(tree.rootNode); } getViewDU(node) { return this.tree_toValue(node); } commitView(view) { return this.commitViewDU(view); } // there is no respective ViewDU for this type commitViewDU(view, hcOffset = 0, hcByLevel = null) { const uint8Array = new Uint8Array(this.value_serializedSize(view)); const dataView = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength); this.value_serializeToBytes({ uint8Array, dataView }, 0, view); const node = this.tree_deserializeFromBytes({ uint8Array, dataView }, 0, uint8Array.length); if (hcByLevel !== null && node.h0 === null) { getHashComputations(node, hcOffset, hcByLevel); } return node; } cacheOfViewDU() { return; } // Over-write to prevent serialize + deserialize toView(value) { return value; } toViewDU(value) { return value; } // Serialization + deserialization (only value is generic) value_serializeToBytes(output, offset, value) { output.uint8Array.set(value, offset); return offset + value.length; } value_deserializeFromBytes(data, start, end, reuseBytes) { this.assertValidSize(end - start); return slice(data.uint8Array, start, end, reuseBytes); } value_toTree(value) { // this saves 1 allocation of Uint8Array const dataView = new DataView(value.buffer, value.byteOffset, value.byteLength); return this.tree_deserializeFromBytes({ uint8Array: value, dataView }, 0, value.length); } // Merkleization getBlocksBytes(value) { // reallocate this.blocksBuffer if needed if (value.length > this.blocksBuffer.length) { const chunkCount = Math.ceil(value.length / 32); this.blocksBuffer = new Uint8Array(Math.ceil(chunkCount / 2) * 64); } return getBlocksBytes(value, this.blocksBuffer); } // Proofs getPropertyGindex() { // Stop navigating below this type. Must only request complete data return null; } getPropertyType() { throw Error("Must only request ByteArray complete data"); } getIndexProperty() { throw Error("Must only request ByteArray complete data"); } tree_fromProofNode(node) { return { node, done: true }; } tree_getLeafGindices(rootGindex, rootNode) { const byteLen = this.tree_getByteLen(rootNode); const chunkCount = Math.ceil(byteLen / 32); const startIndex = concatGindices([rootGindex, toGindex(this.depth, BigInt(0))]); const gindices = new Array(chunkCount); for (let i = 0, gindex = startIndex; i < chunkCount; i++, gindex++) { gindices[i] = gindex; } // include the length chunk if (this.isList) { gindices.push(concatGindices([rootGindex, LENGTH_GINDEX])); } return gindices; } // JSON fromJson(json) { const value = fromHexString(json); this.assertValidSize(value.length); return value; } toJson(value) { return toHexString(value); } // ByteArray is immutable clone(value) { return value; } equals(a, b) { return byteArrayEquals(a, b); } } export function getBlocksBytes(value, blocksBuffer) { if (value.length > blocksBuffer.length) { throw new Error(`data length ${value.length} exceeds blocksBuffer length ${blocksBuffer.length}`); } blocksBuffer.set(value); const valueLen = value.length; const blockByteLen = Math.ceil(valueLen / 64) * 64; // all padding bytes must be zero, this is similar to set zeroHash(0) blocksBuffer.subarray(valueLen, blockByteLen).fill(0); return blocksBuffer.subarray(0, blockByteLen); } //# sourceMappingURL=byteArray.js.map