diff --git a/packages/ssz/src/type/composite.ts b/packages/ssz/src/type/composite.ts index 8ec9314d..e2cd16bb 100644 --- a/packages/ssz/src/type/composite.ts +++ b/packages/ssz/src/type/composite.ts @@ -240,6 +240,7 @@ export abstract class CompositeType extends Type { const merkleBytes = this.getChunkBytes(value); merkleizeInto(merkleBytes, this.maxChunkCount, output, offset); if (this.cachePermanentRootStruct) { + // Buffer.prototype.slice does not copy memory, Enforce Uint8Array usage https://github.com/nodejs/node/issues/28087 const cachedRoot = Uint8Array.prototype.slice.call(output, offset, offset + 32); (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = cachedRoot; } diff --git a/packages/ssz/src/type/listComposite.ts b/packages/ssz/src/type/listComposite.ts index 17e21954..a8ca7db5 100644 --- a/packages/ssz/src/type/listComposite.ts +++ b/packages/ssz/src/type/listComposite.ts @@ -207,7 +207,12 @@ export class ListCompositeType< merkleizeInto(this.mixInLengthChunkBytes, chunkCount, output, offset); if (this.cachePermanentRootStruct) { - (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = output.slice(offset, offset + 32); + // Buffer.prototype.slice does not copy memory, Enforce Uint8Array usage https://github.com/nodejs/node/issues/28087 + (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = Uint8Array.prototype.slice.call( + output, + offset, + offset + 32 + ); } } diff --git a/packages/ssz/src/type/profile.ts b/packages/ssz/src/type/profile.ts index 03941e4b..fb34bfa2 100644 --- a/packages/ssz/src/type/profile.ts +++ b/packages/ssz/src/type/profile.ts @@ -34,7 +34,6 @@ import {Case} from "../util/strings"; import {BitArray} from "../value/bitArray"; import {mixInActiveFields, setActiveFields} from "./stableContainer"; import {NonOptionalFields, isOptionalType, toNonOptionalType} from "./optional"; -import {allocUnsafe} from "@chainsafe/as-sha256"; /* eslint-disable @typescript-eslint/member-ordering */ type BytesRange = {start: number; end: number}; @@ -89,6 +88,8 @@ export class ProfileType>> extends C protected readonly TreeView: ContainerTreeViewTypeConstructor; protected readonly TreeViewDU: ContainerTreeViewDUTypeConstructor; private optionalFieldsCount: number; + // temporary root to avoid memory allocation + private tempRoot = new Uint8Array(32); constructor(readonly fields: Fields, activeFields: BitArray, readonly opts?: ProfileOptions) { super(); @@ -378,13 +379,11 @@ export class ProfileType>> extends C } const merkleBytes = this.getChunkBytes(value); - const root = allocUnsafe(32); - merkleizeInto(merkleBytes, this.maxChunkCount, root, 0); - mixInActiveFields(root, this.activeFields, root, 0); - output.set(root, offset); + merkleizeInto(merkleBytes, this.maxChunkCount, this.tempRoot, 0); + mixInActiveFields(this.tempRoot, this.activeFields, output, offset); if (this.cachePermanentRootStruct) { - (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = root; + (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = this.tempRoot.slice(); } } diff --git a/packages/ssz/src/type/stableContainer.ts b/packages/ssz/src/type/stableContainer.ts index 334fa66a..4a4f0186 100644 --- a/packages/ssz/src/type/stableContainer.ts +++ b/packages/ssz/src/type/stableContainer.ts @@ -38,7 +38,6 @@ import { import {Case} from "../util/strings"; import {isOptionalType, toNonOptionalType, NonOptionalFields} from "./optional"; import {BitArray} from "../value/bitArray"; -import {allocUnsafe} from "@chainsafe/as-sha256"; /* eslint-disable @typescript-eslint/member-ordering */ type BytesRange = {start: number; end: number}; @@ -94,6 +93,8 @@ export class StableContainerType>> e protected readonly TreeView: ContainerTreeViewTypeConstructor; protected readonly TreeViewDU: ContainerTreeViewDUTypeConstructor; private padActiveFields: boolean[]; + // temporary root to avoid memory allocation + private tempRoot = new Uint8Array(32); constructor(fields: Fields, readonly maxFields: number, readonly opts?: StableContainerOptions) { super(); @@ -351,18 +352,16 @@ export class StableContainerType>> e } const merkleBytes = this.getChunkBytes(value); - const root = allocUnsafe(32); - merkleizeInto(merkleBytes, this.maxChunkCount, root, 0); + merkleizeInto(merkleBytes, this.maxChunkCount, this.tempRoot, 0); // compute active field bitvector const activeFields = BitArray.fromBoolArray([ ...this.fieldsEntries.map(({fieldName}) => value[fieldName] != null), ...this.padActiveFields, ]); - mixInActiveFields(root, activeFields, root, 0); - output.set(root, offset); + mixInActiveFields(this.tempRoot, activeFields, output, offset); if (this.cachePermanentRootStruct) { - (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = root; + (value as ValueWithCachedPermanentRoot)[symbolCachedPermanentRoot] = this.tempRoot.slice(); } }