Socket
Socket
Sign inDemoInstall

@chainsafe/ssz

Package Overview
Dependencies
Maintainers
4
Versions
71
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@chainsafe/ssz - npm Package Compare versions

Comparing version 0.7.1 to 0.8.0

lib/backings/readonlyIterate.d.ts

6

CHANGELOG.md

@@ -0,1 +1,7 @@

## 0.8.0 (2021-03-29)
## BREAKING CHANGES
- Refactor codebase ([c86871](https://github.com/chainsafe/ssz/commit/c86871))
## 0.7.1 (2021-03-29)

@@ -2,0 +8,0 @@

13

lib/backings/backedValue.d.ts

@@ -1,7 +0,4 @@

import { TreeBacked } from "./tree";
import { ByteArrayBacked } from "./byteArray";
export declare enum BackingType {
tree = "tree",
byteArray = "byteArray"
}
import { CompositeValue } from "../interface";
import { ITreeBacked } from "./tree";
export declare type Path = (string | number)[];
/**

@@ -14,3 +11,3 @@ * A BackedValue is a value that is backed by a non-structural type

*/
export declare type BackedValue<T extends object> = TreeBacked<T> | ByteArrayBacked<T>;
export declare function isBackedValue<T extends object>(value: T): value is BackedValue<T>;
export declare type BackedValue<T extends CompositeValue> = ITreeBacked<T> & T;
export declare function isBackedValue<T extends CompositeValue>(value: unknown): value is BackedValue<T>;

@@ -7,26 +7,8 @@ "use strict";

exports.isBackedValue = isBackedValue;
exports.BackingType = void 0;
let BackingType;
/**
* A BackedValue is a value that is backed by a non-structural type
*
* It is implemented as an ES6 Proxy object that provides
* - convenient access to the structural properties corresponding to its type
* - additional methods for backing-specific implementations of ssz operations
*/
exports.BackingType = BackingType;
var _tree = require("./tree");
(function (BackingType) {
BackingType["tree"] = "tree";
BackingType["byteArray"] = "byteArray";
})(BackingType || (exports.BackingType = BackingType = {}));
function isBackedValue(value) {
if (value && value.backingType) {
return true;
} else {
return false;
}
return (0, _tree.isTreeBacked)(value);
}
//# sourceMappingURL=backedValue.js.map

@@ -1,6 +0,3 @@

export * from "./object";
export * from "./structural";
export * from "./tree";
export * from "./byteArray";
export * from "./backedValue";
export * from "./readOnlyIterate";
export * from "./readonlyIterate";

@@ -7,26 +7,2 @@ "use strict";

var _object = require("./object");
Object.keys(_object).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _object[key];
}
});
});
var _structural = require("./structural");
Object.keys(_structural).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _structural[key];
}
});
});
var _tree = require("./tree");

@@ -44,14 +20,2 @@

var _byteArray = require("./byteArray");
Object.keys(_byteArray).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _byteArray[key];
}
});
});
var _backedValue = require("./backedValue");

@@ -69,5 +33,5 @@

var _readOnlyIterate = require("./readOnlyIterate");
var _readonlyIterate = require("./readonlyIterate");
Object.keys(_readOnlyIterate).forEach(function (key) {
Object.keys(_readonlyIterate).forEach(function (key) {
if (key === "default" || key === "__esModule") return;

@@ -77,3 +41,3 @@ Object.defineProperty(exports, key, {

get: function get() {
return _readOnlyIterate[key];
return _readonlyIterate[key];
}

@@ -80,0 +44,0 @@ });

@@ -1,8 +0,2 @@

export * from "./abstract";
export * from "./array";
export * from "./vector";
export * from "./list";
export * from "./bitList";
export * from "./bitVector";
export * from "./byteVector";
export * from "./container";
export * from "./interface";
export * from "./treeValue";

@@ -7,5 +7,5 @@ "use strict";

var _abstract = require("./abstract");
var _interface = require("./interface");
Object.keys(_abstract).forEach(function (key) {
Object.keys(_interface).forEach(function (key) {
if (key === "default" || key === "__esModule") return;

@@ -15,3 +15,3 @@ Object.defineProperty(exports, key, {

get: function get() {
return _abstract[key];
return _interface[key];
}

@@ -21,5 +21,5 @@ });

var _array = require("./array");
var _treeValue = require("./treeValue");
Object.keys(_array).forEach(function (key) {
Object.keys(_treeValue).forEach(function (key) {
if (key === "default" || key === "__esModule") return;

@@ -29,78 +29,6 @@ Object.defineProperty(exports, key, {

get: function get() {
return _array[key];
return _treeValue[key];
}
});
});
var _vector = require("./vector");
Object.keys(_vector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _vector[key];
}
});
});
var _list = require("./list");
Object.keys(_list).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _list[key];
}
});
});
var _bitList = require("./bitList");
Object.keys(_bitList).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _bitList[key];
}
});
});
var _bitVector = require("./bitVector");
Object.keys(_bitVector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _bitVector[key];
}
});
});
var _byteVector = require("./byteVector");
Object.keys(_byteVector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _byteVector[key];
}
});
});
var _container = require("./container");
Object.keys(_container).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _container[key];
}
});
});
//# sourceMappingURL=index.js.map

@@ -5,1 +5,3 @@ export * from "./interface";

export { hash } from "./util/compat";
export * from "./util/byteArray";
export * from "./util/tree";

@@ -56,2 +56,28 @@ "use strict";

var _compat = require("./util/compat");
var _byteArray = require("./util/byteArray");
Object.keys(_byteArray).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _byteArray[key];
}
});
});
var _tree = require("./util/tree");
Object.keys(_tree).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _tree[key];
}
});
});
//# sourceMappingURL=index.js.map

@@ -9,5 +9,2 @@ /**

[Symbol.iterator](): Iterator<T>;
find(fn: (value: T, index: number, array: this) => boolean): T | undefined;
findIndex(fn: (value: T, index: number, array: this) => boolean): number;
forEach(fn: (value: T, index: number, array: this) => void): void;
}

@@ -26,2 +23,3 @@ export declare type Vector<T> = ArrayLike<T>;

}
export declare type CompositeValue = Record<string, unknown> | ArrayLike<unknown> | {};
/**

@@ -28,0 +26,0 @@ * The Json interface is used for json-serializable input

@@ -11,11 +11,5 @@ import { Type } from "../type";

constructor();
struct_clone(value: T): T;
struct_equals(value1: T, value2: T): boolean;
/**
* Clone / copy
*/
clone(value: T): T;
/**
* Equality
*/
equals(value1: T, value2: T): boolean;
/**
* Check if type has a variable number of elements (or subelements)

@@ -25,37 +19,8 @@ *

*/
isVariableSize(): boolean;
/**
* Serialized byte length
*/
size(): number;
/**
* Maximal serialized byte length
*/
maxSize(): number;
/**
* Minimal serialized byte length
*/
minSize(): number;
/**
* Validate bytes before calling fromBytes
* @param data
* @param offset
*/
validateBytes(data: Uint8Array, offset: number): void;
/**
* Low-level deserialization
*/
abstract fromBytes(data: Uint8Array, offset: number): T;
/**
* Deserialization
*/
deserialize(data: Uint8Array): T;
/**
* Serialization
*/
serialize(value: T): Uint8Array;
/**
* Merkleization
*/
hashTreeRoot(value: T): Uint8Array;
hasVariableSerializedLength(): boolean;
getMaxSerializedLength(): number;
getMinSerializedLength(): number;
bytes_validate(data: Uint8Array, offset: number): void;
abstract struct_deserializeFromBytes(data: Uint8Array, offset: number): T;
struct_hashTreeRoot(value: T): Uint8Array;
}

@@ -11,2 +11,4 @@ "use strict";

/* eslint-disable @typescript-eslint/camelcase */
/* eslint-disable @typescript-eslint/member-ordering */

@@ -34,21 +36,12 @@

}
/**
* Clone / copy
*/
clone(value) {
struct_clone(value) {
return value;
}
/**
* Equality
*/
equals(value1, value2) {
struct_equals(value1, value2) {
this.assertValidValue(value1);
this.assertValidValue(value2);
return value1 === value2;
} // Serialization / Deserialization
}
/**

@@ -61,37 +54,15 @@ * Check if type has a variable number of elements (or subelements)

isVariableSize() {
hasVariableSerializedLength() {
return false;
}
/**
* Serialized byte length
*/
size() {
throw new Error("Not implemented");
getMaxSerializedLength() {
return this.struct_getSerializedLength();
}
/**
* Maximal serialized byte length
*/
maxSize() {
return this.size();
getMinSerializedLength() {
return this.struct_getSerializedLength();
}
/**
* Minimal serialized byte length
*/
minSize() {
return this.size();
}
/**
* Validate bytes before calling fromBytes
* @param data
* @param offset
*/
validateBytes(data, offset) {
bytes_validate(data, offset) {
if (!data) {

@@ -107,36 +78,11 @@ throw new Error("Data is null or undefined");

if (length < this.size()) {
throw new Error("Data length of ".concat(length, " is too small, expect ").concat(this.size()));
if (length < this.struct_getSerializedLength()) {
throw new Error("Data length of ".concat(length, " is too small, expect ").concat(this.struct_getSerializedLength()));
} // accept data length > this.size()
}
/**
* Low-level deserialization
*/
/**
* Deserialization
*/
deserialize(data) {
return this.fromBytes(data, 0);
}
/**
* Serialization
*/
serialize(value) {
const output = new Uint8Array(this.size());
this.toBytes(value, output, 0);
return output;
}
/**
* Merkleization
*/
hashTreeRoot(value) {
struct_hashTreeRoot(value) {
const output = new Uint8Array(32);
this.toBytes(value, output, 0);
this.struct_serializeToBytes(value, output, 0);
return output;

@@ -143,0 +89,0 @@ }

@@ -8,10 +8,9 @@ import { Json } from "../../interface";

constructor();
size(): number;
isBasic(): boolean;
assertValidValue(value: unknown): asserts value is boolean;
defaultValue(): boolean;
toBytes(value: boolean, output: Uint8Array, offset: number): number;
fromBytes(data: Uint8Array, offset: number): boolean;
fromJson(data: Json): boolean;
toJson(value: boolean): Json;
struct_getSerializedLength(): number;
struct_assertValidValue(value: unknown): asserts value is boolean;
struct_defaultValue(): boolean;
struct_serializeToBytes(value: boolean, output: Uint8Array, offset: number): number;
struct_deserializeFromBytes(data: Uint8Array, offset: number): boolean;
struct_convertFromJson(data: Json): boolean;
struct_convertToJson(value: boolean): Json;
}

@@ -13,2 +13,3 @@ "use strict";

/* eslint-disable @typescript-eslint/camelcase */
const BOOLEAN_TYPE = Symbol.for("ssz/BooleanType");

@@ -28,11 +29,7 @@ exports.BOOLEAN_TYPE = BOOLEAN_TYPE;

size() {
struct_getSerializedLength() {
return 1;
}
isBasic() {
return true;
}
assertValidValue(value) {
struct_assertValidValue(value) {
if (value !== true && value !== false) {

@@ -43,7 +40,7 @@ throw new Error("Boolean value must be true or false");

defaultValue() {
struct_defaultValue() {
return false;
}
toBytes(value, output, offset) {
struct_serializeToBytes(value, output, offset) {
output[offset] = value ? 1 : 0;

@@ -53,4 +50,4 @@ return offset + 1;

fromBytes(data, offset) {
this.validateBytes(data, offset);
struct_deserializeFromBytes(data, offset) {
this.bytes_validate(data, offset);

@@ -66,8 +63,8 @@ if (data[offset] === 1) {

fromJson(data) {
this.assertValidValue(data);
struct_convertFromJson(data) {
this.struct_assertValidValue(data);
return data;
}
toJson(value) {
struct_convertToJson(value) {
return value;

@@ -74,0 +71,0 @@ }

@@ -12,3 +12,3 @@ import { Json } from "../../interface";

constructor(options: IUintOptions);
size(): number;
struct_getSerializedLength(): number;
}

@@ -18,10 +18,11 @@ export declare const NUMBER_UINT_TYPE: unique symbol;

export declare class NumberUintType extends UintType<number> {
_maxBigInt: BigInt;
constructor(options: IUintOptions);
assertValidValue(value: unknown): asserts value is number;
defaultValue(): number;
maxBigInt(): BigInt;
toBytes(value: number, output: Uint8Array, offset: number): number;
fromBytes(data: Uint8Array, offset: number): number;
fromJson(data: Json): number;
toJson(value: number): Json;
struct_assertValidValue(value: unknown): asserts value is number;
struct_defaultValue(): number;
struct_getMaxBigInt(): BigInt;
struct_serializeToBytes(value: number, output: Uint8Array, offset: number): number;
struct_deserializeFromBytes(data: Uint8Array, offset: number): number;
struct_convertFromJson(data: Json): number;
struct_convertToJson(value: number): Json;
}

@@ -32,10 +33,8 @@ export declare const BIGINT_UINT_TYPE: unique symbol;

constructor(options: IUintOptions);
assertValidValue(value: unknown): asserts value is bigint;
defaultValue(): bigint;
toBytes(value: bigint, output: Uint8Array, offset: number): number;
/**
*/
fromBytes(data: Uint8Array, offset: number): bigint;
fromJson(data: Json): bigint;
toJson(value: bigint): Json;
struct_assertValidValue(value: unknown): asserts value is bigint;
struct_defaultValue(): bigint;
struct_serializeToBytes(value: bigint, output: Uint8Array, offset: number): number;
struct_deserializeFromBytes(data: Uint8Array, offset: number): bigint;
struct_convertFromJson(data: Json): bigint;
struct_convertToJson(value: bigint): Json;
}

@@ -36,3 +36,3 @@ "use strict";

size() {
struct_getSerializedLength() {
return this.byteLength;

@@ -56,6 +56,8 @@ }

_defineProperty(this, "_maxBigInt", void 0);
this._typeSymbols.add(NUMBER_UINT_TYPE);
}
assertValidValue(value) {
struct_assertValidValue(value) {
if (value !== Infinity && (!Number.isSafeInteger(value) || value > BigInt(2) ** (BigInt(8) * BigInt(this.byteLength)))) {

@@ -70,11 +72,15 @@ throw new Error("Uint value is not a number");

defaultValue() {
struct_defaultValue() {
return 0;
}
maxBigInt() {
return BigInt(2) ** BigInt(this.byteLength * 8) - BigInt(1);
struct_getMaxBigInt() {
if (this._maxBigInt === undefined) {
this._maxBigInt = BigInt(2) ** BigInt(this.byteLength * 8) - BigInt(1);
}
return this._maxBigInt;
}
toBytes(value, output, offset) {
struct_serializeToBytes(value, output, offset) {
if (this.byteLength > 6 && value === Infinity) {

@@ -97,4 +103,4 @@ for (let i = offset; i < offset + this.byteLength; i++) {

fromBytes(data, offset) {
this.validateBytes(data, offset);
struct_deserializeFromBytes(data, offset) {
this.bytes_validate(data, offset);
let isInfinity = true;

@@ -118,7 +124,7 @@ let output = 0;

fromJson(data) {
struct_convertFromJson(data) {
let n;
const bigN = BigInt(data);
if (bigN === this.maxBigInt()) {
if (bigN === this.struct_getMaxBigInt()) {
n = Infinity;

@@ -135,6 +141,6 @@ } else if (bigN < Number.MAX_SAFE_INTEGER) {

toJson(value) {
struct_convertToJson(value) {
if (this.byteLength > 4) {
if (value === Infinity) {
return this.maxBigInt().toString();
return this.struct_getMaxBigInt().toString();
}

@@ -165,3 +171,3 @@

assertValidValue(value) {
struct_assertValidValue(value) {
if (typeof value !== "bigint") {

@@ -176,7 +182,7 @@ throw new Error("Uint value is not a bigint");

defaultValue() {
struct_defaultValue() {
return BigInt(0);
}
toBytes(value, output, offset) {
struct_serializeToBytes(value, output, offset) {
// Motivation

@@ -202,8 +208,5 @@ // BigInt bit shifting and BigInt allocation is slower compared to number

}
/**
*/
fromBytes(data, offset) {
this.validateBytes(data, offset); // Motivation:
struct_deserializeFromBytes(data, offset) {
this.bytes_validate(data, offset); // Motivation:
// Creating BigInts and bitshifting is more expensive than

@@ -251,3 +254,3 @@ // number bitshifting.

fromJson(data) {
struct_convertFromJson(data) {
const value = BigInt(data);

@@ -258,3 +261,3 @@ this.assertValidValue(value);

toJson(value) {
struct_convertToJson(value) {
if (this.byteLength > 4) {

@@ -261,0 +264,0 @@ return value.toString();

@@ -1,6 +0,7 @@

import { Json } from "../../interface";
import { BackedValue, ByteArrayHandler, StructuralHandler, TreeHandler } from "../../backings";
import { CompositeValue, Json } from "../../interface";
import { BackedValue, Path, TreeBacked } from "../../backings";
import { IJsonOptions, Type } from "../type";
import { Gindex, Node, Proof, Tree } from "@chainsafe/persistent-merkle-tree";
export declare const COMPOSITE_TYPE: unique symbol;
export declare function isCompositeType(type: Type<unknown>): type is CompositeType<object>;
export declare function isCompositeType(type: Type<unknown>): type is CompositeType<CompositeValue>;
/**

@@ -10,7 +11,59 @@ * A CompositeType is a type containing other types, and is flexible in its representation.

*/
export declare abstract class CompositeType<T extends object> extends Type<T> {
structural: StructuralHandler<T>;
tree: TreeHandler<T>;
byteArray: ByteArrayHandler<T>;
export declare abstract class CompositeType<T extends CompositeValue> extends Type<T> {
_chunkDepth: number;
_defaultNode: Node;
constructor();
abstract struct_assertValidValue(value: unknown): asserts value is T;
abstract struct_equals(struct1: T, struct2: T): boolean;
tree_equals(tree1: Tree, tree2: Tree): boolean;
bytes_equals(bytes1: Uint8Array, bytes2: Uint8Array): boolean;
abstract struct_defaultValue(): T;
abstract tree_defaultNode(): Node;
tree_defaultValue(): Tree;
abstract struct_clone(value: T): T;
tree_clone(value: Tree): Tree;
bytes_clone(value: Uint8Array, start?: number, end?: number): Uint8Array;
abstract struct_convertToJson(struct: T, options?: IJsonOptions): Json;
abstract struct_convertFromJson(json: Json, options?: IJsonOptions): T;
abstract struct_convertToTree(struct: T): Tree;
abstract tree_convertToStruct(tree: Tree): T;
abstract struct_serializeToBytes(struct: T, output: Uint8Array, offset: number): number;
abstract tree_serializeToBytes(tree: Tree, output: Uint8Array, offset: number): number;
struct_serialize(struct: T, data: Uint8Array): number;
tree_serialize(tree: Tree, data: Uint8Array): number;
bytes_validate(data: Uint8Array, start: number, end: number): void;
abstract struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
abstract tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
struct_deserialize(data: Uint8Array): T;
tree_deserialize(data: Uint8Array): Tree;
abstract getMinSerializedLength(): number;
abstract getMaxSerializedLength(): number;
abstract struct_getSerializedLength(struct: T): number;
abstract tree_getSerializedLength(tree: Tree): number;
abstract hasVariableSerializedLength(): boolean;
abstract bytes_getVariableOffsets(target: Uint8Array): [number, number][];
abstract getMaxChunkCount(): number;
struct_getChunkCount(struct: T): number;
tree_getChunkCount(target: Tree): number;
abstract struct_getRootAtChunkIndex(struct: T, chunkIx: number): Uint8Array;
struct_yieldChunkRoots(struct: T): Iterable<Uint8Array>;
getChunkDepth(): number;
getGindexAtChunkIndex(index: number): Gindex;
tree_getSubtreeAtChunkIndex(target: Tree, index: number): Tree;
tree_setSubtreeAtChunkIndex(target: Tree, index: number, value: Tree, expand?: boolean): void;
tree_getRootAtChunkIndex(target: Tree, index: number): Uint8Array;
tree_setRootAtChunkIndex(target: Tree, index: number, value: Uint8Array, expand?: boolean): void;
abstract struct_getPropertyNames(struct: T): (string | number)[];
abstract tree_getPropertyNames(tree: Tree): (string | number)[];
abstract getPropertyGindex(property: PropertyKey): Gindex;
getPathGindex(path: Path): Gindex;
abstract getPropertyType(property: PropertyKey): Type<unknown> | undefined;
abstract tree_getProperty(tree: Tree, property: PropertyKey): Tree | unknown;
abstract tree_setProperty(tree: Tree, property: PropertyKey, value: Tree | unknown): boolean;
abstract tree_deleteProperty(tree: Tree, property: PropertyKey): boolean;
abstract tree_iterateValues(tree: Tree): IterableIterator<Tree | unknown>;
abstract tree_readonlyIterateValues(tree: Tree): IterableIterator<Tree | unknown>;
tree_createProof(target: Tree, paths: Path[]): Proof;
struct_hashTreeRoot(struct: T): Uint8Array;
tree_hashTreeRoot(tree: Tree): Uint8Array;
/**

@@ -31,7 +84,7 @@ * Valid value assertion

*/
clone(value: BackedValue<T> | T): BackedValue<T> | T;
clone(value: T): T;
/**
* Serialized byte length
*/
size(value: BackedValue<T> | T): number;
size(value: T): number;
/**

@@ -58,15 +111,11 @@ * Maximal serialized byte length

*/
toBytes(value: BackedValue<T> | T, output: Uint8Array, offset: number): number;
toBytes(value: T, output: Uint8Array, offset: number): number;
/**
* Serialization
*/
serialize(value: BackedValue<T> | T): Uint8Array;
serialize(value: T): Uint8Array;
/**
* Return the number of leaf chunks to be merkleized
*/
abstract chunkCount(): number;
/**
* Merkleization
*/
hashTreeRoot(value: BackedValue<T> | T): Uint8Array;
hashTreeRoot(value: T): Uint8Array;
/**

@@ -80,2 +129,7 @@ * Convert from a JSON-serializable object

toJson(value: T, options?: IJsonOptions): Json;
createTreeBacked(tree: Tree): TreeBacked<T>;
createTreeBackedFromStruct(value: T): TreeBacked<T>;
createTreeBackedFromBytes(data: Uint8Array): TreeBacked<T>;
createTreeBackedFromJson(data: Json, options?: IJsonOptions): TreeBacked<T>;
defaultTreeBacked(): TreeBacked<T>;
}

@@ -13,2 +13,8 @@ "use strict";

var _persistentMerkleTree = require("@chainsafe/persistent-merkle-tree");
var _compat = require("../../util/compat");
var _byteArray = require("../../util/byteArray");
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

@@ -32,10 +38,161 @@

_defineProperty(this, "structural", void 0);
_defineProperty(this, "_chunkDepth", void 0);
_defineProperty(this, "tree", void 0);
_defineProperty(this, "_defaultNode", void 0);
_defineProperty(this, "byteArray", void 0);
this._typeSymbols.add(COMPOSITE_TYPE);
}
tree_equals(tree1, tree2) {
return (0, _byteArray.byteArrayEquals)(tree1.root, tree2.root);
}
bytes_equals(bytes1, bytes2) {
return (0, _byteArray.byteArrayEquals)(bytes1, bytes2);
}
tree_defaultValue() {
return new _persistentMerkleTree.Tree(this.tree_defaultNode());
}
tree_clone(value) {
return value.clone();
}
bytes_clone(value, start = 0, end = value.length) {
const bytes = new Uint8Array(end - start);
value.subarray(start, end).set(bytes);
return bytes;
}
struct_serialize(struct, data) {
const output = new Uint8Array(this.struct_getSerializedLength(struct));
return this.struct_serializeToBytes(struct, output, 0);
}
tree_serialize(tree, data) {
const output = new Uint8Array(this.tree_getSerializedLength(tree));
return this.tree_serializeToBytes(tree, output, 0);
}
bytes_validate(data, start, end) {
if (!data) {
throw new Error("Data is null or undefined");
}
if (data.length === 0) {
throw new Error("Data is empty");
}
if (start < 0) {
throw new Error("Start param is negative: ".concat(start));
}
if (start > data.length) {
throw new Error("Start param: ".concat(start, " is greater than length: ").concat(data.length));
}
if (end < 0) {
throw new Error("End param is negative: ".concat(end));
}
if (end > data.length) {
throw new Error("End param: ".concat(end, " is greater than length: ").concat(data.length));
}
const length = end - start;
if (!this.hasVariableSerializedLength() && length !== this.struct_getSerializedLength(null)) {
throw new Error("Incorrect data length ".concat(length, ", expect ").concat(this.struct_getSerializedLength(null)));
}
if (end - start < this.getMinSerializedLength()) {
throw new Error("Data length ".concat(length, " is too small, expect at least ").concat(this.getMinSerializedLength()));
}
}
struct_deserialize(data) {
return this.struct_deserializeFromBytes(data, 0, data.length);
}
tree_deserialize(data) {
return this.tree_deserializeFromBytes(data, 0, data.length);
}
struct_getChunkCount(struct) {
return this.getMaxChunkCount();
}
tree_getChunkCount(target) {
return this.getMaxChunkCount();
}
*struct_yieldChunkRoots(struct) {
const chunkCount = this.struct_getChunkCount(struct);
for (let i = 0; i < chunkCount; i++) {
yield this.struct_getRootAtChunkIndex(struct, i);
}
}
getChunkDepth() {
if (!this._chunkDepth) {
this._chunkDepth = (0, _persistentMerkleTree.countToDepth)(BigInt(this.getMaxChunkCount()));
}
return this._chunkDepth;
}
getGindexAtChunkIndex(index) {
return (0, _persistentMerkleTree.toGindex)(this.getChunkDepth(), BigInt(index));
}
tree_getSubtreeAtChunkIndex(target, index) {
return target.getSubtree(this.getGindexAtChunkIndex(index));
}
tree_setSubtreeAtChunkIndex(target, index, value, expand = false) {
target.setSubtree(this.getGindexAtChunkIndex(index), value, expand);
}
tree_getRootAtChunkIndex(target, index) {
return target.getRoot(this.getGindexAtChunkIndex(index));
}
tree_setRootAtChunkIndex(target, index, value, expand = false) {
target.setRoot(this.getGindexAtChunkIndex(index), value, expand);
}
getPathGindex(path) {
const gindices = [];
let type = this;
for (const prop of path) {
if (!isCompositeType(type)) {
throw new Error("Invalid path: cannot navigate beyond a basic type");
}
gindices.push(type.getPropertyGindex(prop));
type = type.getPropertyType(prop);
}
return (0, _persistentMerkleTree.concatGindices)(gindices);
}
tree_createProof(target, paths) {
const gindices = paths.map(path => this.getPathGindex(path));
return target.getProof({
type: _persistentMerkleTree.ProofType.treeOffset,
gindices
});
}
struct_hashTreeRoot(struct) {
return (0, _compat.merkleize)(this.struct_yieldChunkRoots(struct), this.getMaxChunkCount());
}
tree_hashTreeRoot(tree) {
return tree.root;
} // convenience
/**

@@ -47,3 +204,3 @@ * Valid value assertion

assertValidValue(value) {
this.structural.assertValidValue(value);
this.struct_assertValidValue(value);
}

@@ -59,3 +216,3 @@ /**

} else {
return this.structural.equals(value1, value2);
return this.struct_equals(value1, value2);
}

@@ -69,3 +226,3 @@ }

defaultValue() {
return this.structural.defaultValue();
return this.struct_defaultValue();
}

@@ -81,3 +238,3 @@ /**

} else {
return this.structural.clone(value);
return this.struct_clone(value);
}

@@ -95,3 +252,3 @@ } // Serialization / Deserialization

} else {
return this.structural.size(value);
return this.struct_getSerializedLength(value);
}

@@ -105,3 +262,3 @@ }

maxSize() {
return this.structural.maxSize();
return this.getMaxSerializedLength();
}

@@ -114,3 +271,3 @@ /**

minSize() {
return this.structural.minSize();
return this.getMinSerializedLength();
}

@@ -123,3 +280,3 @@ /**

fromBytes(data, start, end) {
return this.structural.fromBytes(data, start, end);
return this.struct_deserializeFromBytes(data, start, end);
}

@@ -132,3 +289,3 @@ /**

deserialize(data) {
return this.structural.deserialize(data);
return this.fromBytes(data, 0, data.length);
}

@@ -146,3 +303,3 @@ /**

} else {
return this.structural.toBytes(value, output, offset);
return this.struct_serializeToBytes(value, output, offset);
}

@@ -159,3 +316,5 @@ }

} else {
return this.structural.serialize(value);
const output = new Uint8Array(this.size(value));
this.toBytes(value, output, 0);
return output;
}

@@ -165,9 +324,6 @@ } // Merkleization

/**
* Return the number of leaf chunks to be merkleized
* Merkleization
*/
/**
* Merkleization
*/
hashTreeRoot(value) {

@@ -177,3 +333,3 @@ if ((0, _backings.isBackedValue)(value)) {

} else {
return this.structural.hashTreeRoot(value);
return this.struct_hashTreeRoot(value);
}

@@ -187,3 +343,3 @@ }

fromJson(data, options) {
return this.structural.fromJson(data, options);
return this.struct_convertFromJson(data, options);
}

@@ -196,5 +352,25 @@ /**

toJson(value, options) {
return this.structural.toJson(value, options);
return this.struct_convertToJson(value, options);
}
createTreeBacked(tree) {
return (0, _backings.createTreeBacked)(this, tree);
}
createTreeBackedFromStruct(value) {
return this.createTreeBacked(this.struct_convertToTree(value));
}
createTreeBackedFromBytes(data) {
return this.createTreeBacked(this.tree_deserialize(data));
}
createTreeBackedFromJson(data, options) {
return this.createTreeBackedFromStruct(this.struct_convertFromJson(data, options));
}
defaultTreeBacked() {
return (0, _backings.createTreeBacked)(this, this.tree_defaultValue());
}
}

@@ -201,0 +377,0 @@

@@ -1,5 +0,6 @@

import { ArrayLike } from "../../interface";
import { Type } from "../type";
import { ArrayLike, CompositeValue, Json } from "../../interface";
import { IJsonOptions, Type } from "../type";
import { BasicType } from "../basic";
import { CompositeType } from "./abstract";
import { Gindex, Tree } from "@chainsafe/persistent-merkle-tree";
export interface IArrayOptions {

@@ -11,6 +12,69 @@ elementType: Type<any>;

constructor(options: IArrayOptions);
abstract struct_getLength(value: T): number;
abstract getMaxLength(): number;
abstract getMinLength(): number;
struct_getSerializedLength(value: T): number;
getMaxSerializedLength(): number;
getMinSerializedLength(): number;
struct_assertValidValue(value: unknown): asserts value is T;
struct_equals(value1: T, value2: T): boolean;
struct_clone(value: T): T;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_serializeToBytes(value: T, output: Uint8Array, offset: number): number;
struct_getRootAtChunkIndex(value: T, index: number): Uint8Array;
struct_getPropertyNames(value: T): (string | number)[];
struct_convertFromJson(data: Json[]): T;
struct_convertToJson(value: T): Json;
struct_convertToTree(value: T): Tree;
tree_convertToStruct(target: Tree): T;
abstract tree_getLength(target: Tree): number;
tree_getSerializedLength(target: Tree): number;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
tree_serializeToBytes(target: Tree, output: Uint8Array, offset: number): number;
getPropertyGindex(prop: PropertyKey): Gindex;
getPropertyType(prop: PropertyKey): BasicType<unknown>;
tree_iterateValues(target: Tree): IterableIterator<Tree | unknown>;
tree_readonlyIterateValues(target: Tree): IterableIterator<Tree | unknown>;
getChunkOffset(index: number): number;
getChunkIndex(index: number): number;
tree_getValueAtIndex(target: Tree, index: number): T[number];
tree_setValueAtIndex(target: Tree, index: number, value: T[number], expand?: boolean): boolean;
tree_getProperty(target: Tree, property: keyof T): T[keyof T];
tree_setProperty(target: Tree, property: number, value: T[number], expand?: boolean): boolean;
tree_deleteProperty(target: Tree, property: number): boolean;
tree_getPropertyNames(target: Tree): string[];
bytes_getVariableOffsets(target: Uint8Array): [number, number][];
}
export declare abstract class CompositeArrayType<T extends ArrayLike<unknown>> extends CompositeType<T> {
elementType: CompositeType<object>;
elementType: CompositeType<CompositeValue>;
constructor(options: IArrayOptions);
abstract struct_getLength(value: T): number;
abstract getMaxLength(): number;
abstract getMinLength(): number;
struct_getSerializedLength(value: T): number;
getMaxSerializedLength(): number;
getMinSerializedLength(): number;
struct_assertValidValue(value: unknown): asserts value is T;
struct_equals(value1: T, value2: T): boolean;
struct_clone(value: T): T;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_serializeToBytes(value: T, output: Uint8Array, offset: number): number;
struct_getRootAtChunkIndex(value: T, index: number): Uint8Array;
struct_getPropertyNames(value: T): (string | number)[];
struct_convertFromJson(data: Json[], options?: IJsonOptions): T;
struct_convertToJson(value: T, options?: IJsonOptions): Json;
struct_convertToTree(value: T): Tree;
tree_convertToStruct(target: Tree): T;
abstract tree_getLength(target: Tree): number;
tree_getSerializedLength(target: Tree): number;
tree_serializeToBytes(target: Tree, output: Uint8Array, offset: number): number;
getPropertyGindex(prop: PropertyKey): Gindex;
getPropertyType(prop: PropertyKey): CompositeType<CompositeValue>;
tree_getProperty<V extends keyof T>(target: Tree, property: V): Tree | unknown;
tree_setProperty(target: Tree, property: number, value: Tree, expand?: boolean): boolean;
tree_deleteProperty(target: Tree, property: number): boolean;
tree_getPropertyNames(target: Tree): (string | number)[];
tree_iterateValues(target: Tree): IterableIterator<Tree | unknown>;
tree_readonlyIterateValues(target: Tree): IterableIterator<Tree | unknown>;
bytes_getVariableOffsets(target: Uint8Array): [number, number][];
}

@@ -10,2 +10,6 @@ "use strict";

var _errorPath = require("../../util/errorPath");
var _persistentMerkleTree = require("@chainsafe/persistent-merkle-tree");
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

@@ -22,2 +26,270 @@

struct_getSerializedLength(value) {
return this.elementType.struct_getSerializedLength() * this.struct_getLength(value);
}
getMaxSerializedLength() {
return this.getMaxLength() * this.elementType.getMaxSerializedLength();
}
getMinSerializedLength() {
return this.getMinLength() * this.elementType.getMinSerializedLength();
}
struct_assertValidValue(value) {
for (let i = 0; i < this.struct_getLength(value); i++) {
try {
this.elementType.struct_assertValidValue(value[i]);
} catch (e) {
throw new Error("Invalid element ".concat(i, ": ").concat(e.message));
}
}
}
struct_equals(value1, value2) {
if (this.struct_getLength(value1) !== this.struct_getLength(value2)) {
return false;
}
for (let i = 0; i < this.struct_getLength(value1); i++) {
if (!this.elementType.struct_equals(value1[i], value2[i])) {
return false;
}
}
return true;
}
struct_clone(value) {
const newValue = this.struct_defaultValue();
for (let i = 0; i < this.struct_getLength(value); i++) {
newValue[i] = this.elementType.struct_clone(value[i]);
}
return newValue;
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
const elementSize = this.elementType.struct_getSerializedLength();
return Array.from({
length: (end - start) / elementSize
}, (_, i) => this.elementType.struct_deserializeFromBytes(data, start + i * elementSize));
}
struct_serializeToBytes(value, output, offset) {
const length = this.struct_getLength(value);
let index = offset;
for (let i = 0; i < length; i++) {
index = this.elementType.struct_serializeToBytes(value[i], output, index);
}
return index;
}
struct_getRootAtChunkIndex(value, index) {
const output = new Uint8Array(32);
const itemSize = this.elementType.struct_getSerializedLength();
const itemsInChunk = Math.floor(32 / itemSize);
const firstIndex = index * itemsInChunk; // not inclusive
const lastIndex = Math.min(this.struct_getLength(value), firstIndex + itemsInChunk); // i = array index, grows by 1
// j = data offset, grows by itemSize
for (let i = firstIndex, j = 0; i < lastIndex; i++, j += itemSize) {
this.elementType.struct_serializeToBytes(value[i], output, j);
}
return output;
}
struct_getPropertyNames(value) {
const length = this.struct_getLength(value);
return Array.from({
length
}, (_, i) => i).concat(["length"]);
}
struct_convertFromJson(data) {
return Array.from({
length: data.length
}, (_, i) => this.elementType.fromJson(data[i]));
}
struct_convertToJson(value) {
return Array.from({
length: this.struct_getLength(value)
}, (_, i) => this.elementType.struct_convertToJson(value[i]));
}
struct_convertToTree(value) {
const contents = [];
for (const chunk of this.struct_yieldChunkRoots(value)) {
contents.push(new _persistentMerkleTree.LeafNode(chunk));
}
return new _persistentMerkleTree.Tree((0, _persistentMerkleTree.subtreeFillToContents)(contents, this.getChunkDepth()));
}
tree_convertToStruct(target) {
const value = this.struct_defaultValue();
const length = this.tree_getLength(target);
for (let i = 0; i < length; i++) {
value[i] = this.tree_getValueAtIndex(target, i);
}
return value;
}
tree_getSerializedLength(target) {
return this.elementType.struct_getSerializedLength() * this.tree_getLength(target);
}
tree_deserializeFromBytes(data, start, end) {
const target = this.tree_defaultValue();
const byteLength = end - start;
const chunkCount = Math.ceil(byteLength / 32);
for (let i = 0; i < chunkCount; i++) {
// view of the chunk, shared buffer from `data`
const dataChunk = new Uint8Array(data.buffer, data.byteOffset + start + i * 32, Math.min(32, byteLength - i * 32)); // copy chunk into new memory
const chunk = new Uint8Array(32);
chunk.set(dataChunk);
this.tree_setRootAtChunkIndex(target, i, chunk, true // expand tree as needed
);
}
return target;
}
tree_serializeToBytes(target, output, offset) {
const size = this.tree_getSerializedLength(target);
const fullChunkCount = Math.floor(size / 32);
const remainder = size % 32;
let i = 0;
if (fullChunkCount > 0) {
for (const node of target.iterateNodesAtDepth(this.getChunkDepth(), 0, fullChunkCount)) {
output.set(node.root, offset + i * 32);
i++;
}
}
if (remainder) {
output.set(this.tree_getRootAtChunkIndex(target, fullChunkCount).slice(0, remainder), offset + i * 32);
}
return offset + size;
}
getPropertyGindex(prop) {
return this.getGindexAtChunkIndex(this.getChunkIndex(prop));
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
getPropertyType(prop) {
return this.elementType;
}
*tree_iterateValues(target) {
const length = this.tree_getLength(target);
if (length === 0) {
return;
}
const elementSize = this.elementType.struct_getSerializedLength();
if (32 % elementSize !== 0) {
throw new Error("cannot handle a non-chunk-alignable elementType");
}
let left = length;
for (const node of target.iterateNodesAtDepth(this.getChunkDepth(), 0, this.tree_getChunkCount(target))) {
const chunk = node.root;
for (let offset = 0; offset < 32; offset += elementSize) {
yield this.elementType.struct_deserializeFromBytes(chunk, offset);
left--;
if (left === 0) {
return;
}
}
}
}
*tree_readonlyIterateValues(target) {
yield* this.tree_iterateValues(target);
}
getChunkOffset(index) {
const elementSize = this.elementType.struct_getSerializedLength();
return index % Math.ceil(32 / elementSize) * elementSize;
}
getChunkIndex(index) {
return Math.floor(index / Math.ceil(32 / this.elementType.struct_getSerializedLength()));
}
tree_getValueAtIndex(target, index) {
const chunk = this.tree_getRootAtChunkIndex(target, this.getChunkIndex(index));
return this.elementType.struct_deserializeFromBytes(chunk, this.getChunkOffset(index));
}
tree_setValueAtIndex(target, index, value, expand = false) {
const chunkGindex = this.getGindexAtChunkIndex(this.getChunkIndex(index)); // copy data from old chunk, use new memory to set a new chunk
const chunk = new Uint8Array(32);
chunk.set(target.getRoot(chunkGindex));
this.elementType.struct_serializeToBytes(value, chunk, this.getChunkOffset(index));
target.setRoot(chunkGindex, chunk, expand);
return true;
}
tree_getProperty(target, property) {
const length = this.tree_getLength(target);
if (property === "length") {
return length;
}
const index = Number(property);
if (Number.isNaN(index)) {
return undefined;
}
if (index >= length) {
return undefined;
}
return this.tree_getValueAtIndex(target, index);
}
tree_setProperty(target, property, value, expand = false) {
return this.tree_setValueAtIndex(target, property, value, expand);
}
tree_deleteProperty(target, property) {
return this.tree_setProperty(target, property, this.elementType.struct_defaultValue());
}
tree_getPropertyNames(target) {
return Array.from({
length: this.tree_getLength(target)
}, (_, i) => String(i)).concat("length");
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
bytes_getVariableOffsets(target) {
return [];
}
}

@@ -36,2 +308,333 @@

struct_getSerializedLength(value) {
if (this.elementType.hasVariableSerializedLength()) {
let s = 0;
for (let i = 0; i < this.struct_getLength(value); i++) {
s += this.elementType.struct_getSerializedLength(value[i]) + 4;
}
return s;
} else {
return this.elementType.struct_getSerializedLength(null) * this.struct_getLength(value);
}
}
getMaxSerializedLength() {
if (this.elementType.hasVariableSerializedLength()) {
return this.getMaxLength() * 4 + this.getMaxLength() * this.elementType.getMaxSerializedLength();
} else {
return this.getMaxLength() * this.elementType.getMaxSerializedLength();
}
}
getMinSerializedLength() {
if (this.elementType.hasVariableSerializedLength()) {
return this.getMinLength() * 4 + this.getMinLength() * this.elementType.getMinSerializedLength();
} else {
return this.getMinLength() * this.elementType.getMinSerializedLength();
}
}
struct_assertValidValue(value) {
for (let i = 0; i < this.struct_getLength(value); i++) {
try {
this.elementType.struct_assertValidValue(value[i]);
} catch (e) {
throw new Error("Invalid element ".concat(i, ": ").concat(e.message));
}
}
}
struct_equals(value1, value2) {
if (this.struct_getLength(value1) !== this.struct_getLength(value2)) {
return false;
}
for (let i = 0; i < this.struct_getLength(value1); i++) {
if (!this.elementType.struct_equals(value1[i], value2[i])) {
return false;
}
}
return true;
}
struct_clone(value) {
const newValue = this.struct_defaultValue();
for (let i = 0; i < this.struct_getLength(value); i++) {
newValue[i] = this.elementType.struct_clone(value[i]);
}
return newValue;
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
if (start === end) {
return [];
}
if (this.elementType.hasVariableSerializedLength()) {
const value = []; // all elements variable-sized
// indices contain offsets
let currentIndex = start;
let nextIndex; // data exists between offsets
const fixedSection = new DataView(data.buffer, data.byteOffset);
const firstOffset = start + fixedSection.getUint32(start, true);
let currentOffset = firstOffset;
let nextOffset;
while (currentIndex < firstOffset) {
if (currentOffset > end) {
throw new Error("Offset out of bounds");
}
nextIndex = currentIndex + 4;
nextOffset = nextIndex === firstOffset ? end : start + fixedSection.getUint32(nextIndex, true);
if (currentOffset > nextOffset) {
throw new Error("Offsets must be increasing");
}
try {
value.push(this.elementType.struct_deserializeFromBytes(data, currentOffset, nextOffset));
} catch (e) {
throw new _errorPath.SszErrorPath(e, value.length);
}
currentIndex = nextIndex;
currentOffset = nextOffset;
}
if (firstOffset !== currentIndex) {
throw new Error("First offset skips variable data");
}
return value;
} else {
const elementSize = this.elementType.struct_getSerializedLength(null);
return Array.from({
length: (end - start) / elementSize
}, (_, i) => this.elementType.struct_deserializeFromBytes(data, start + i * elementSize, start + (i + 1) * elementSize));
}
}
struct_serializeToBytes(value, output, offset) {
const length = this.struct_getLength(value);
if (this.elementType.hasVariableSerializedLength()) {
let variableIndex = offset + length * 4;
const fixedSection = new DataView(output.buffer, output.byteOffset + offset);
for (let i = 0; i < length; i++) {
// write offset
fixedSection.setUint32(i * 4, variableIndex - offset, true); // write serialized element to variable section
variableIndex = this.elementType.struct_serializeToBytes(value[i], output, variableIndex);
}
return variableIndex;
} else {
let index = offset;
for (let i = 0; i < length; i++) {
index = this.elementType.struct_serializeToBytes(value[i], output, index);
}
return index;
}
}
struct_getRootAtChunkIndex(value, index) {
return this.elementType.hashTreeRoot(value[index]);
}
struct_getPropertyNames(value) {
const length = this.struct_getLength(value);
return Array.from({
length
}, (_, i) => i).concat(["length"]);
}
struct_convertFromJson(data, options) {
return Array.from({
length: data.length
}, (_, i) => this.elementType.struct_convertFromJson(data[i], options));
}
struct_convertToJson(value, options) {
return Array.from({
length: this.struct_getLength(value)
}, (_, i) => this.elementType.struct_convertToJson(value[i], options));
}
struct_convertToTree(value) {
const contents = [];
for (const element of value) {
contents.push(this.elementType.struct_convertToTree(element).rootNode);
}
return new _persistentMerkleTree.Tree((0, _persistentMerkleTree.subtreeFillToContents)(contents, this.getChunkDepth()));
}
tree_convertToStruct(target) {
const value = this.struct_defaultValue();
const length = this.tree_getLength(target);
for (let i = 0; i < length; i++) {
value[i] = this.elementType.tree_convertToStruct(this.tree_getSubtreeAtChunkIndex(target, i));
}
return value;
}
tree_getSerializedLength(target) {
if (this.elementType.hasVariableSerializedLength()) {
let s = 0;
for (let i = 0; i < this.tree_getLength(target); i++) {
s += this.elementType.tree_getSerializedLength(this.tree_getSubtreeAtChunkIndex(target, i)) + 4;
}
return s;
} else {
return this.elementType.tree_getSerializedLength(null) * this.tree_getLength(target);
}
}
tree_serializeToBytes(target, output, offset) {
const length = this.tree_getLength(target);
if (this.elementType.hasVariableSerializedLength()) {
let variableIndex = offset + length * 4;
const fixedSection = new DataView(output.buffer, output.byteOffset + offset, length * 4);
let i = 0;
for (const node of target.iterateNodesAtDepth(this.getChunkDepth(), i, length)) {
// write offset
fixedSection.setUint32(i * 4, variableIndex - offset, true); // write serialized element to variable section
variableIndex = this.elementType.tree_serializeToBytes(new _persistentMerkleTree.Tree(node), output, variableIndex);
i++;
}
return variableIndex;
} else {
let index = offset;
let i = 0;
for (const node of target.iterateNodesAtDepth(this.getChunkDepth(), i, length)) {
index = this.elementType.tree_serializeToBytes(new _persistentMerkleTree.Tree(node), output, index);
i++;
}
return index;
}
}
getPropertyGindex(prop) {
return this.getGindexAtChunkIndex(prop);
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
getPropertyType(prop) {
return this.elementType;
}
tree_getProperty(target, property) {
const length = this.tree_getLength(target);
if (property === "length") {
return length;
}
const index = Number(property);
if (Number.isNaN(index)) {
return undefined;
}
if (index >= length) {
return undefined;
}
return this.tree_getSubtreeAtChunkIndex(target, index);
}
tree_setProperty(target, property, value, expand = false) {
this.tree_setSubtreeAtChunkIndex(target, property, value, expand);
return true;
}
tree_deleteProperty(target, property) {
return this.tree_setProperty(target, property, this.elementType.tree_defaultValue());
}
tree_getPropertyNames(target) {
return Array.from({
length: this.tree_getLength(target)
}, (_, i) => i).concat(["length"]);
}
*tree_iterateValues(target) {
for (const gindex of (0, _persistentMerkleTree.iterateAtDepth)(this.getChunkDepth(), BigInt(0), BigInt(this.tree_getLength(target)))) {
yield target.getSubtree(gindex);
}
}
*tree_readonlyIterateValues(target) {
for (const node of target.iterateNodesAtDepth(this.getChunkDepth(), 0, this.tree_getLength(target))) {
yield new _persistentMerkleTree.Tree(node);
}
}
bytes_getVariableOffsets(target) {
if (this.elementType.hasVariableSerializedLength()) {
if (target.length === 0) {
return [];
}
const offsets = []; // all elements are variable-sized
// indices contain offsets, which are indices deeper in the byte array
const fixedSection = new DataView(target.buffer, target.byteOffset);
const firstOffset = fixedSection.getUint32(0, true);
let currentOffset = firstOffset;
let nextOffset;
let currentIndex = 0;
let nextIndex = 0;
while (currentIndex < firstOffset) {
if (currentOffset > target.length) {
throw new Error("Offset out of bounds");
}
nextIndex = currentIndex + 4;
nextOffset = nextIndex === firstOffset ? target.length : fixedSection.getUint32(nextIndex, true);
if (currentOffset > nextOffset) {
throw new Error("Offsets must be increasing");
}
offsets.push([currentOffset, nextOffset]);
currentIndex = nextIndex;
currentOffset = nextOffset;
}
if (firstOffset !== currentIndex) {
throw new Error("First offset skips variable data");
}
return offsets;
} else {
return [];
}
}
}

@@ -38,0 +641,0 @@

@@ -1,4 +0,5 @@

import { BitList } from "../../interface";
import { BitList, Json } from "../../interface";
import { BasicListType } from "./list";
import { Type } from "../type";
import { Tree } from "@chainsafe/persistent-merkle-tree";
export interface IBitListOptions {

@@ -11,3 +12,25 @@ limit: number;

constructor(options: IBitListOptions);
chunkCount(): number;
struct_getByte(value: BitList, index: number): number;
struct_getLength(value: BitList): number;
struct_getByteLength(value: BitList): number;
struct_getSerializedLength(value: BitList): number;
getMaxSerializedLength(): number;
getMinSerializedLength(): number;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): BitList;
struct_serializeToBytes(value: BitList, output: Uint8Array, offset: number): number;
struct_getRootAtChunkIndex(value: BitList, index: number): Uint8Array;
struct_convertFromJson(data: Json): BitList;
struct_convertToJson(value: BitList): Json;
tree_getByteLength(target: Tree): number;
tree_getSerializedLength(target: Tree): number;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
tree_serializeToBytes(target: Tree, output: Uint8Array, offset: number): number;
getBitOffset(index: number): number;
getChunkOffset(index: number): number;
getChunkIndex(index: number): number;
tree_getChunkCount(target: Tree): number;
tree_iterateValues(target: Tree): IterableIterator<Tree | unknown>;
tree_getValueAtIndex(target: Tree, index: number): boolean;
tree_setValueAtIndex(target: Tree, property: number, value: boolean, expand?: boolean): boolean;
getMaxChunkCount(): number;
}

@@ -15,3 +15,3 @@ "use strict";

var _backings = require("../../backings");
var _byteArray = require("../../util/byteArray");

@@ -36,4 +36,2 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

}, options));
this.structural = new _backings.BitListStructuralHandler(this);
this.tree = new _backings.BitListTreeHandler(this);

@@ -43,3 +41,219 @@ this._typeSymbols.add(BITLIST_TYPE);

chunkCount() {
struct_getByte(value, index) {
const firstBitIndex = index * 8;
const lastBitIndex = Math.min(firstBitIndex + 7, value.length - 1);
let bitstring = "0b";
for (let i = lastBitIndex; i >= firstBitIndex; i--) {
bitstring += value[i] ? "1" : "0";
}
return Number(bitstring);
}
struct_getLength(value) {
return value.length;
}
struct_getByteLength(value) {
return Math.ceil(value.length / 8);
}
struct_getSerializedLength(value) {
if (value.length % 8 === 0) {
return this.struct_getByteLength(value) + 1;
} else {
return this.struct_getByteLength(value);
}
}
getMaxSerializedLength() {
return Math.ceil(this.limit / 8) + 1;
}
getMinSerializedLength() {
return 1;
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
const value = [];
const toBool = c => c === "1" ? true : false;
for (let i = start; i < end - 1; i++) {
let bitstring = data[i].toString(2);
bitstring = "0".repeat(8 - bitstring.length) + bitstring;
value.push(...Array.prototype.map.call(bitstring, toBool).reverse());
}
const lastByte = data[end - 1];
if (lastByte === 0) {
throw new Error("Invalid deserialized bitlist, padding bit required");
}
if (lastByte === 1) {
return value;
}
const lastBits = Array.prototype.map.call(lastByte.toString(2), toBool).reverse();
const last1 = lastBits.lastIndexOf(true);
value.push(...lastBits.slice(0, last1));
if (value.length > this.limit) {
throw new Error("Invalid deserialized bitlist, length greater than limit");
}
return value;
}
struct_serializeToBytes(value, output, offset) {
const byteLength = this.struct_getByteLength(value);
for (let i = 0; i < byteLength; i++) {
output[offset + i] = this.struct_getByte(value, i);
}
const newOffset = offset + byteLength;
if (value.length % 8 === 0) {
output[newOffset] = 1;
return newOffset + 1;
} else {
output[newOffset - 1] |= 1 << value.length % 8;
return newOffset;
}
}
struct_getRootAtChunkIndex(value, index) {
const output = new Uint8Array(32);
const byteLength = Math.min(32, this.struct_getByteLength(value) - index * 32);
for (let i = 0; i < byteLength; i++) {
output[i] = this.struct_getByte(value, i + index);
}
return output;
}
struct_convertFromJson(data) {
const bytes = (0, _byteArray.fromHexString)(data);
return this.struct_deserializeFromBytes(bytes, 0, bytes.length);
}
struct_convertToJson(value) {
return (0, _byteArray.toHexString)(this.serialize(value));
}
tree_getByteLength(target) {
return Math.ceil(this.tree_getLength(target) / 8);
}
tree_getSerializedLength(target) {
const bitLength = this.tree_getLength(target);
if (bitLength % 8 === 0) {
return this.tree_getByteLength(target) + 1;
} else {
return this.tree_getByteLength(target);
}
}
tree_deserializeFromBytes(data, start, end) {
const lastByte = data[end - 1];
if (lastByte === 0) {
throw new Error("Invalid deserialized bitlist, padding bit required");
}
const target = super.tree_deserializeFromBytes(data, start, end);
const lastGindex = this.getGindexAtChunkIndex(Math.ceil((end - start) / 32) - 1); // copy chunk into new memory
const lastChunk = new Uint8Array(32);
lastChunk.set(target.getRoot(lastGindex));
const lastChunkByte = (end - start) % 32 - 1;
let length;
if (lastByte === 1) {
// zero lastChunkByte
length = (end - start - 1) * 8;
lastChunk[lastChunkByte] = 0;
} else {
// mask lastChunkByte
const lastByteBitLength = lastByte.toString(2).length - 1;
length = (end - start - 1) * 8 + lastByteBitLength;
const mask = 0xff >> 8 - lastByteBitLength;
lastChunk[lastChunkByte] &= mask;
}
target.setRoot(lastGindex, lastChunk);
this.tree_setLength(target, length);
return target;
}
tree_serializeToBytes(target, output, offset) {
const newOffset = super.tree_serializeToBytes(target, output, offset);
const bitLength = this.tree_getLength(target);
const size = this.tree_getSerializedLength(target); // set padding bit
output[offset + size - 1] |= 1 << bitLength % 8;
return newOffset;
}
getBitOffset(index) {
return index % 8;
}
getChunkOffset(index) {
return Math.floor(index % 256 / 8);
}
getChunkIndex(index) {
return Math.floor(index / 256);
}
tree_getChunkCount(target) {
return Math.ceil(this.tree_getLength(target) / 256);
}
*tree_iterateValues(target) {
const length = this.tree_getLength(target);
const chunkCount = this.tree_getChunkCount(target);
const nodeIterator = target.iterateNodesAtDepth(this.getChunkDepth(), 0, chunkCount);
let i = 0;
for (const node of nodeIterator) {
const chunk = node.root;
for (let j = 0; j < 256 && i < length; i++, j++) {
const byte = chunk[this.getChunkOffset(i)];
yield !!(byte & 1 << this.getBitOffset(i));
}
}
}
tree_getValueAtIndex(target, index) {
const chunk = this.tree_getRootAtChunkIndex(target, this.getChunkIndex(index));
const byte = chunk[this.getChunkOffset(index)];
return !!(byte & 1 << this.getBitOffset(index));
}
tree_setValueAtIndex(target, property, value, expand = false) {
const chunkGindex = this.getGindexAtChunkIndex(this.getChunkIndex(property));
const chunk = new Uint8Array(32);
chunk.set(target.getRoot(chunkGindex));
const byteOffset = this.getChunkOffset(property);
if (value) {
chunk[byteOffset] |= 1 << this.getBitOffset(property);
} else {
chunk[byteOffset] &= 0xff ^ 1 << this.getBitOffset(property);
}
target.setRoot(chunkGindex, chunk, expand);
return true;
}
getMaxChunkCount() {
return Math.ceil(this.limit / 256);

@@ -46,0 +260,0 @@ }

@@ -1,4 +0,5 @@

import { BitVector } from "../../interface";
import { BitVector, Json } from "../../interface";
import { BasicVectorType } from "./vector";
import { Type } from "../type";
import { Tree } from "@chainsafe/persistent-merkle-tree";
export interface IBitVectorOptions {

@@ -11,3 +12,24 @@ length: number;

constructor(options: IBitVectorOptions);
chunkCount(): number;
struct_getLength(value: BitVector): number;
struct_getByteLength(value: BitVector): number;
struct_getSerializedLength(value: BitVector): number;
getMaxSerializedLength(): number;
getMinSerializedLength(): number;
struct_getByte(value: BitVector, index: number): number;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): BitVector;
struct_serializeToBytes(value: BitVector, output: Uint8Array, offset: number): number;
struct_getRootAtChunkIndex(value: BitVector, index: number): Uint8Array;
struct_convertFromJson(data: Json): BitVector;
struct_convertToJson(value: BitVector): Json;
tree_getByteLength(target: Tree): number;
tree_getSerializedLength(target: Tree): number;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
getBitOffset(index: number): number;
getChunkOffset(index: number): number;
getChunkIndex(index: number): number;
tree_getChunkCount(target: Tree): number;
tree_iterateValues(target: Tree): IterableIterator<Tree | unknown>;
tree_getValueAtIndex(target: Tree, index: number): boolean;
tree_setProperty(target: Tree, property: number, value: boolean): boolean;
getMaxChunkCount(): number;
}

@@ -15,3 +15,3 @@ "use strict";

var _backings = require("../../backings");
var _byteArray = require("../../util/byteArray");

@@ -36,9 +36,177 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

}, options));
this.structural = new _backings.BitVectorStructuralHandler(this);
this.tree = new _backings.BitVectorTreeHandler(this);
this._typeSymbols.add(BITVECTOR_TYPE);
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
struct_getLength(value) {
return this.length;
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
struct_getByteLength(value) {
return Math.ceil(this.length / 8);
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
struct_getSerializedLength(value) {
return Math.ceil(this.length / 8);
}
chunkCount() {
getMaxSerializedLength() {
return this.struct_getSerializedLength(null);
}
getMinSerializedLength() {
return this.struct_getSerializedLength(null);
}
struct_getByte(value, index) {
const firstBitIndex = index * 8;
const lastBitIndex = Math.min(firstBitIndex + 7, value.length - 1);
let bitstring = "0b";
for (let i = lastBitIndex; i >= firstBitIndex; i--) {
bitstring += value[i] ? "1" : "0";
}
return Number(bitstring);
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
if (end - start !== this.size(null)) {
throw new Error("Invalid bitvector: length not equal to vector length");
}
const value = [];
for (let i = start; i < end - 1; i++) {
value.push(...(0, _byteArray.getByteBits)(data, i));
}
const lastBitLength = this.length % 8;
if (!lastBitLength) {
// vector takes up the whole byte, no need for checks
value.push(...(0, _byteArray.getByteBits)(data, end - 1));
} else {
const lastBits = (0, _byteArray.getByteBits)(data, end - 1);
if (lastBits.slice(lastBitLength).some(b => b)) {
throw new Error("Invalid bitvector: nonzero bits past length");
}
value.push(...lastBits.slice(0, lastBitLength));
}
return value;
}
struct_serializeToBytes(value, output, offset) {
const byteLength = this.struct_getByteLength(value);
for (let i = 0; i < byteLength; i++) {
output[offset + i] = this.struct_getByte(value, i);
}
return offset + byteLength;
}
struct_getRootAtChunkIndex(value, index) {
const output = new Uint8Array(32);
const byteLength = Math.min(32, this.struct_getByteLength(value) - index);
for (let i = 0; i < byteLength; i++) {
output[i] = this.struct_getByte(value, i + index);
}
return output;
}
struct_convertFromJson(data) {
const bytes = (0, _byteArray.fromHexString)(data);
return this.fromBytes(bytes, 0, bytes.length);
}
struct_convertToJson(value) {
return (0, _byteArray.toHexString)(this.serialize(value));
}
tree_getByteLength(target) {
return Math.ceil(this.tree_getLength(target) / 8);
}
tree_getSerializedLength(target) {
return this.tree_getByteLength(target);
}
tree_deserializeFromBytes(data, start, end) {
// mask last byte to ensure it doesn't go over length
const lastByte = data[end - 1];
const mask = 0xff << this.length % 8 & 0xff;
if (lastByte & mask) {
throw new Error("Invalid deserialized bitvector length");
}
return super.tree_deserializeFromBytes(data, start, end);
}
getBitOffset(index) {
return index % 8;
}
getChunkOffset(index) {
return Math.floor(index % 256 / 8);
}
getChunkIndex(index) {
return Math.floor(index / 256);
}
tree_getChunkCount(target) {
return Math.ceil(this.tree_getLength(target) / 256);
}
*tree_iterateValues(target) {
const length = this.tree_getLength(target);
const chunkCount = this.tree_getChunkCount(target);
const nodeIterator = target.iterateNodesAtDepth(this.getChunkDepth(), 0, chunkCount);
let i = 0;
for (const node of nodeIterator) {
const chunk = node.root;
for (let j = 0; j < 256 && i < length; i++, j++) {
const byte = chunk[this.getChunkOffset(i)];
yield !!(byte & 1 << this.getBitOffset(i));
}
}
}
tree_getValueAtIndex(target, index) {
const chunk = this.tree_getRootAtChunkIndex(target, this.getChunkIndex(index));
const byte = chunk[this.getChunkOffset(index)];
return !!(byte & 1 << this.getBitOffset(index));
}
tree_setProperty(target, property, value) {
const chunkGindex = this.getGindexAtChunkIndex(this.getChunkIndex(property));
const chunk = new Uint8Array(32);
chunk.set(target.getRoot(chunkGindex));
const byteOffset = this.getChunkOffset(property);
if (value) {
chunk[byteOffset] |= 1 << this.getBitOffset(property);
} else {
chunk[byteOffset] &= 0xff ^ 1 << this.getBitOffset(property);
}
target.setRoot(chunkGindex, chunk);
return true;
}
getMaxChunkCount() {
return Math.ceil(this.length / 256);

@@ -45,0 +213,0 @@ }

@@ -1,4 +0,5 @@

import { ByteVector } from "../../interface";
import { ByteVector, Json } from "../../interface";
import { BasicVectorType } from "./vector";
import { Type } from "../type";
import { Tree } from "@chainsafe/persistent-merkle-tree";
export interface IByteVectorOptions {

@@ -11,2 +12,8 @@ length: number;

constructor(options: IByteVectorOptions);
struct_defaultValue(): ByteVector;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): ByteVector;
struct_serializeToBytes(value: ByteVector, output: Uint8Array, offset: number): number;
struct_convertFromJson(data: Json): ByteVector;
struct_convertToJson(value: ByteVector): Json;
tree_convertToStruct(target: Tree): ByteVector;
}

@@ -15,3 +15,3 @@ "use strict";

var _backings = require("../../backings");
var _byteArray = require("../../util/byteArray");

@@ -36,4 +36,2 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

}, options));
this.structural = new _backings.ByteVectorStructuralHandler(this);
this.tree = new _backings.ByteVectorTreeHandler(this);

@@ -43,2 +41,59 @@ this._typeSymbols.add(BYTEVECTOR_TYPE);

struct_defaultValue() {
return new Uint8Array(this.length);
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
const length = end - start;
if (length !== this.length) {
throw new Error("Invalid deserialized vector length: expected ".concat(this.length, ", actual: ").concat(length));
}
const value = new Uint8Array(length);
value.set(data.slice(start, end));
return value;
}
struct_serializeToBytes(value, output, offset) {
output.set(value, offset);
return offset + this.length;
}
struct_convertFromJson(data) {
const value = (0, _byteArray.fromHexString)(data);
if (value.length !== this.length) {
throw new Error("Invalid JSON vector length: expected ".concat(this.length, ", actual: ").concat(value.length));
}
return value;
}
struct_convertToJson(value) {
return (0, _byteArray.toHexString)(value);
}
tree_convertToStruct(target) {
const value = new Uint8Array(this.length);
const chunkIterator = target.iterateNodesAtDepth(this.getChunkDepth(), 0, this.getMaxChunkCount());
if (this.length % 32 === 0) {
for (let i = 0; i < this.length; i += 32) {
value.set(chunkIterator.next().value.root, i);
}
} else {
let i;
for (i = 0; i < this.length - 32; i += 32) {
value.set(chunkIterator.next().value.root, i);
}
value.set(chunkIterator.next().value.root.subarray(0, this.length - i), i);
}
return value;
}
}

@@ -45,0 +100,0 @@

@@ -1,4 +0,5 @@

import { ObjectLike } from "../../interface";
import { Json, ObjectLike } from "../../interface";
import { CompositeType } from "./abstract";
import { Type } from "../type";
import { IJsonOptions, Type } from "../type";
import { Gindex, Node, Tree } from "@chainsafe/persistent-merkle-tree";
export interface IContainerOptions {

@@ -12,4 +13,32 @@ fields: Record<string, Type<any>>;

constructor(options: IContainerOptions);
isVariableSize(): boolean;
chunkCount(): number;
struct_defaultValue(): T;
struct_getSerializedLength(value: T): number;
getMaxSerializedLength(): number;
getMinSerializedLength(): number;
struct_assertValidValue(value: unknown): asserts value is T;
struct_equals(value1: T, value2: T): boolean;
struct_clone(value: T): T;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_serializeToBytes(value: T, output: Uint8Array, offset: number): number;
struct_getRootAtChunkIndex(value: T, index: number): Uint8Array;
struct_convertFromJson(data: Json, options?: IJsonOptions): T;
struct_convertToJson(value: T, options?: IJsonOptions): Json;
struct_convertToTree(value: T): Tree;
struct_getPropertyNames(): (string | number)[];
bytes_getVariableOffsets(target: Uint8Array): [number, number][];
tree_defaultNode(): Node;
tree_convertToStruct(target: Tree): T;
tree_getSerializedLength(target: Tree): number;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
tree_serializeToBytes(target: Tree, output: Uint8Array, offset: number): number;
getPropertyGindex(prop: PropertyKey): Gindex;
getPropertyType(prop: PropertyKey): Type<unknown>;
tree_getPropertyNames(): (string | number)[];
tree_getProperty(target: Tree, prop: PropertyKey): Tree | unknown;
tree_setProperty(target: Tree, property: PropertyKey, value: Tree | unknown): boolean;
tree_deleteProperty(target: Tree, prop: PropertyKey): boolean;
tree_iterateValues(target: Tree): IterableIterator<Tree | unknown>;
tree_readonlyIterateValues(target: Tree): IterableIterator<Tree | unknown>;
hasVariableSerializedLength(): boolean;
getMaxChunkCount(): number;
}

@@ -13,4 +13,8 @@ "use strict";

var _backings = require("../../backings");
var _persistentMerkleTree = require("@chainsafe/persistent-merkle-tree");
var _errorPath = require("../../util/errorPath");
var _json = require("../../util/json");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

@@ -38,5 +42,2 @@

this.fields = _objectSpread({}, options.fields);
this.structural = new _backings.ContainerStructuralHandler(this);
this.tree = new _backings.ContainerTreeHandler(this);
this.byteArray = new _backings.ContainerByteArrayHandler(this);

@@ -46,7 +47,460 @@ this._typeSymbols.add(CONTAINER_TYPE);

isVariableSize() {
return Object.values(this.fields).some(fieldType => fieldType.isVariableSize());
struct_defaultValue() {
const obj = {};
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
obj[fieldName] = fieldType.struct_defaultValue();
});
return obj;
}
chunkCount() {
struct_getSerializedLength(value) {
let s = 0;
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
if (fieldType.hasVariableSerializedLength()) {
s += fieldType.struct_getSerializedLength(value[fieldName]) + 4;
} else {
s += fieldType.struct_getSerializedLength(null);
}
});
return s;
}
getMaxSerializedLength() {
const fixedSize = Object.values(this.fields).reduce((total, fieldType) => total + (fieldType.hasVariableSerializedLength() ? 4 : fieldType.getMaxSerializedLength()), 0);
const maxDynamicSize = Object.values(this.fields).reduce((total, fieldType) => total += fieldType.hasVariableSerializedLength() ? fieldType.getMaxSerializedLength() : 0, 0);
return fixedSize + maxDynamicSize;
}
getMinSerializedLength() {
const fixedSize = Object.values(this.fields).reduce((total, fieldType) => total + (fieldType.hasVariableSerializedLength() ? 4 : fieldType.getMinSerializedLength()), 0);
const minDynamicSize = Object.values(this.fields).reduce((total, fieldType) => total += fieldType.hasVariableSerializedLength() ? fieldType.getMinSerializedLength() : 0, 0);
return fixedSize + minDynamicSize;
}
struct_assertValidValue(value) {
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
try {
// @ts-ignore
fieldType.struct_assertValidValue(value[fieldName]);
} catch (e) {
throw new Error("Invalid field ".concat(fieldName, ": ").concat(e.message));
}
});
}
struct_equals(value1, value2) {
this.struct_assertValidValue(value1);
this.struct_assertValidValue(value2);
return Object.entries(this.fields).every(([fieldName, fieldType]) => {
return fieldType.struct_equals(value1[fieldName], value2[fieldName]);
});
}
struct_clone(value) {
const newValue = {};
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
newValue[fieldName] = fieldType.struct_clone(value[fieldName]);
});
return newValue;
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
let currentIndex = start;
let nextIndex = currentIndex;
const value = {}; // Since variable-sized values can be interspersed with fixed-sized values, we precalculate
// the offset indices so we can more easily deserialize the fields in once pass
// first we get the fixed sizes
const fixedSizes = Object.values(this.fields).map(fieldType => !fieldType.hasVariableSerializedLength() && fieldType.struct_getSerializedLength(null)); // with the fixed sizes, we can read the offsets, and store for our single pass
const offsets = [];
const fixedSection = new DataView(data.buffer, data.byteOffset);
const fixedEnd = fixedSizes.reduce((index, size) => {
if (size === false) {
offsets.push(start + fixedSection.getUint32(index, true));
return index + 4;
} else {
return index + size;
}
}, start);
offsets.push(end);
if (fixedEnd !== offsets[0]) {
throw new Error("Not all variable bytes consumed");
}
let offsetIndex = 0;
Object.entries(this.fields).forEach(([fieldName, fieldType], i) => {
try {
const fieldSize = fixedSizes[i];
if (fieldSize === false) {
// variable-sized field
if (offsets[offsetIndex] > end) {
throw new Error("Offset out of bounds");
}
if (offsets[offsetIndex] > offsets[offsetIndex + 1]) {
throw new Error("Offsets must be increasing");
}
value[fieldName] = fieldType.struct_deserializeFromBytes(data, offsets[offsetIndex], offsets[offsetIndex + 1]);
offsetIndex++;
currentIndex += 4;
} else {
// fixed-sized field
nextIndex = currentIndex + fieldSize;
value[fieldName] = fieldType.struct_deserializeFromBytes(data, currentIndex, nextIndex);
currentIndex = nextIndex;
}
} catch (e) {
throw new _errorPath.SszErrorPath(e, fieldName);
}
});
if (offsets.length > 1) {
if (offsetIndex !== offsets.length - 1) {
throw new Error("Not all variable bytes consumed");
}
if (currentIndex !== offsets[0]) {
throw new Error("Not all fixed bytes consumed");
}
} else {
if (currentIndex !== end) {
throw new Error("Not all fixed bytes consumed");
}
}
return value;
}
struct_serializeToBytes(value, output, offset) {
let variableIndex = offset + Object.values(this.fields).reduce((total, fieldType) => total + (fieldType.hasVariableSerializedLength() ? 4 : fieldType.struct_getSerializedLength(null)), 0);
const fixedSection = new DataView(output.buffer, output.byteOffset + offset);
let fixedIndex = offset;
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
if (fieldType.hasVariableSerializedLength()) {
// write offset
fixedSection.setUint32(fixedIndex - offset, variableIndex - offset, true);
fixedIndex += 4; // write serialized element to variable section
variableIndex = fieldType.toBytes(value[fieldName], output, variableIndex);
} else {
fixedIndex = fieldType.toBytes(value[fieldName], output, fixedIndex);
}
});
return variableIndex;
}
struct_getRootAtChunkIndex(value, index) {
const fieldName = Object.keys(this.fields)[index];
const fieldType = this.fields[fieldName];
return fieldType.struct_hashTreeRoot(value[fieldName]);
}
struct_convertFromJson(data, options) {
if (typeof data !== "object") {
throw new Error("Invalid JSON container: expected Object");
}
const value = {};
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
const expectedCase = options ? options.case : null;
const expectedFieldName = (0, _json.toExpectedCase)(fieldName, expectedCase);
if (data[expectedFieldName] === undefined) {
throw new Error("Invalid JSON container field: expected field ".concat(expectedFieldName, " is undefined"));
}
value[fieldName] = fieldType.fromJson(data[expectedFieldName], options);
});
return value;
}
struct_convertToJson(value, options) {
const data = {};
const expectedCase = options ? options.case : null;
Object.entries(this.fields).forEach(([fieldName, fieldType]) => {
data[(0, _json.toExpectedCase)(fieldName, expectedCase)] = fieldType.toJson(value[fieldName], options);
});
return data;
}
struct_convertToTree(value) {
return new _persistentMerkleTree.Tree((0, _persistentMerkleTree.subtreeFillToContents)(Object.entries(this.fields).map(([fieldName, fieldType]) => {
if (!(0, _abstract.isCompositeType)(fieldType)) {
const chunk = new Uint8Array(32);
fieldType.toBytes(value[fieldName], chunk, 0);
return new _persistentMerkleTree.LeafNode(chunk);
} else {
return fieldType.struct_convertToTree(value[fieldName]).rootNode;
}
}), this.getChunkDepth()));
}
struct_getPropertyNames() {
return Object.keys(this.fields);
}
bytes_getVariableOffsets(target) {
const offsets = []; // variable-sized values can be interspersed with fixed-sized values
// variable-sized value indices are serialized as offsets, indices deeper in the byte array
let currentIndex = 0;
let nextIndex = 0;
const fixedSection = new DataView(target.buffer, target.byteOffset);
const fixedOffsets = [];
const variableOffsets = [];
let variableIndex = 0;
Object.values(this.fields).forEach((fieldType, i) => {
if (fieldType.hasVariableSerializedLength()) {
const offset = fixedSection.getUint32(currentIndex, true);
if (offset > target.length) {
throw new Error("Offset out of bounds");
}
variableOffsets.push(offset);
currentIndex = nextIndex = currentIndex + 4;
variableIndex++;
} else {
nextIndex = currentIndex + fieldType.struct_getSerializedLength(null);
fixedOffsets[i] = [currentIndex, nextIndex];
currentIndex = nextIndex;
}
});
variableOffsets.push(target.length);
variableIndex = 0;
Object.values(this.fields).forEach((fieldType, i) => {
if (fieldType.hasVariableSerializedLength()) {
if (variableOffsets[variableIndex] > variableOffsets[variableIndex + 1]) {
throw new Error("Offsets must be increasing");
}
offsets.push([variableOffsets[variableIndex], variableOffsets[variableIndex + 1]]);
variableIndex++;
} else {
offsets.push(fixedOffsets[i]);
}
});
return offsets;
}
tree_defaultNode() {
if (!this._defaultNode) {
this._defaultNode = (0, _persistentMerkleTree.subtreeFillToContents)(Object.values(this.fields).map(fieldType => {
if (!(0, _abstract.isCompositeType)(fieldType)) {
return (0, _persistentMerkleTree.zeroNode)(0);
} else {
return fieldType.tree_defaultNode();
}
}), this.getChunkDepth());
}
return this._defaultNode;
}
tree_convertToStruct(target) {
const value = {};
Object.entries(this.fields).forEach(([fieldName, fieldType], i) => {
if (!(0, _abstract.isCompositeType)(fieldType)) {
const chunk = this.tree_getRootAtChunkIndex(target, i);
value[fieldName] = fieldType.struct_deserializeFromBytes(chunk, 0);
} else {
const subtree = this.tree_getSubtreeAtChunkIndex(target, i);
value[fieldName] = fieldType.tree_convertToStruct(subtree);
}
});
return value;
}
tree_getSerializedLength(target) {
let s = 0;
Object.values(this.fields).forEach((fieldType, i) => {
if (fieldType.hasVariableSerializedLength()) {
s += fieldType.tree_getSerializedLength(this.tree_getSubtreeAtChunkIndex(target, i)) + 4;
} else {
s += fieldType.struct_getSerializedLength(null);
}
});
return s;
}
tree_deserializeFromBytes(data, start, end) {
const target = this.tree_defaultValue();
const offsets = this.bytes_getVariableOffsets(new Uint8Array(data.buffer, data.byteOffset + start, end - start));
Object.values(this.fields).forEach((fieldType, i) => {
const [currentOffset, nextOffset] = offsets[i];
if (!(0, _abstract.isCompositeType)(fieldType)) {
// view of the chunk, shared buffer from `data`
const dataChunk = new Uint8Array(data.buffer, data.byteOffset + start + currentOffset, nextOffset - currentOffset);
const chunk = new Uint8Array(32); // copy chunk into new memory
chunk.set(dataChunk);
this.tree_setRootAtChunkIndex(target, i, chunk);
} else {
this.tree_setSubtreeAtChunkIndex(target, i, fieldType.tree_deserializeFromBytes(data, start + currentOffset, start + nextOffset));
}
});
return target;
}
tree_serializeToBytes(target, output, offset) {
let variableIndex = offset + Object.values(this.fields).reduce((total, fieldType) => total + (fieldType.hasVariableSerializedLength() ? 4 : fieldType.struct_getSerializedLength(null)), 0);
const fixedSection = new DataView(output.buffer, output.byteOffset + offset);
let fixedIndex = offset;
let i = 0;
const fieldTypes = Object.values(this.fields);
for (const node of target.iterateNodesAtDepth(this.getChunkDepth(), i, fieldTypes.length)) {
const fieldType = fieldTypes[i];
if (!(0, _abstract.isCompositeType)(fieldType)) {
const s = fieldType.struct_getSerializedLength();
output.set(node.root.slice(0, s), fixedIndex);
fixedIndex += s;
} else if (fieldType.hasVariableSerializedLength()) {
// write offset
fixedSection.setUint32(fixedIndex - offset, variableIndex - offset, true);
fixedIndex += 4; // write serialized element to variable section
variableIndex = fieldType.tree_serializeToBytes(new _persistentMerkleTree.Tree(node), output, variableIndex);
} else {
fixedIndex = fieldType.tree_serializeToBytes(new _persistentMerkleTree.Tree(node), output, fixedIndex);
}
i++;
}
return variableIndex;
}
getPropertyGindex(prop) {
const chunkIndex = Object.keys(this.fields).findIndex(fieldName => fieldName === prop);
if (chunkIndex === -1) {
throw new Error("Invalid container field name: ".concat(String(prop)));
}
return this.getGindexAtChunkIndex(chunkIndex);
}
getPropertyType(prop) {
const type = this.fields[prop];
if (!type) {
throw new Error("Invalid container field name: ".concat(String(prop)));
}
return type;
}
tree_getPropertyNames() {
return Object.keys(this.fields);
}
tree_getProperty(target, prop) {
const chunkIndex = Object.keys(this.fields).findIndex(fieldName => fieldName === prop);
if (chunkIndex === -1) {
return undefined;
}
const fieldType = this.fields[prop];
if (!(0, _abstract.isCompositeType)(fieldType)) {
const chunk = this.tree_getRootAtChunkIndex(target, chunkIndex);
return fieldType.struct_deserializeFromBytes(chunk, 0);
} else {
return this.tree_getSubtreeAtChunkIndex(target, chunkIndex);
}
}
tree_setProperty(target, property, value) {
const chunkIndex = Object.keys(this.fields).findIndex(fieldName => fieldName === property);
if (chunkIndex === -1) {
throw new Error("Invalid container field name");
}
const chunkGindex = this.getGindexAtChunkIndex(chunkIndex);
const fieldType = this.fields[property];
if (!(0, _abstract.isCompositeType)(fieldType)) {
const chunk = new Uint8Array(32);
fieldType.struct_serializeToBytes(value, chunk, 0);
target.setRoot(chunkGindex, chunk);
return true;
} else {
target.setSubtree(chunkGindex, value);
return true;
}
}
tree_deleteProperty(target, prop) {
const chunkIndex = Object.keys(this.fields).findIndex(fieldName => fieldName === prop);
if (chunkIndex === -1) {
throw new Error("Invalid container field name");
}
const fieldType = this.fields[prop];
if (!(0, _abstract.isCompositeType)(fieldType)) {
return this.tree_setProperty(target, prop, fieldType.struct_defaultValue());
} else {
return this.tree_setProperty(target, prop, fieldType.tree_defaultValue());
}
}
*tree_iterateValues(target) {
const gindexIterator = (0, _persistentMerkleTree.iterateAtDepth)(this.getChunkDepth(), BigInt(0), BigInt(this.getMaxChunkCount()))[Symbol.iterator]();
for (const propType of Object.values(this.fields)) {
const {
value,
done
} = gindexIterator.next();
if (done) {
return;
} else {
if (!(0, _abstract.isCompositeType)(propType)) {
yield propType.struct_deserializeFromBytes(value.root, 0);
} else {
yield target.getSubtree(value);
}
}
}
}
*tree_readonlyIterateValues(target) {
const chunkIterator = target.iterateNodesAtDepth(this.getChunkDepth(), 0, this.getMaxChunkCount());
for (const propType of Object.values(this.fields)) {
const {
value,
done
} = chunkIterator.next();
if (done) {
return;
} else {
if (!(0, _abstract.isCompositeType)(propType)) {
yield propType.struct_deserializeFromBytes(value.root, 0);
} else {
yield new _persistentMerkleTree.Tree(value);
}
}
}
}
hasVariableSerializedLength() {
return Object.values(this.fields).some(fieldType => fieldType.hasVariableSerializedLength());
}
getMaxChunkCount() {
return Object.keys(this.fields).length;

@@ -53,0 +507,0 @@ }

@@ -1,4 +0,5 @@

import { List } from "../../interface";
import { Json, List } from "../../interface";
import { IArrayOptions, BasicArrayType, CompositeArrayType } from "./array";
import { Type } from "../type";
import { IJsonOptions, Type } from "../type";
import { Node, Tree } from "@chainsafe/persistent-merkle-tree";
export interface IListOptions extends IArrayOptions {

@@ -17,4 +18,26 @@ limit: number;

constructor(options: IListOptions);
isVariableSize(): boolean;
chunkCount(): number;
struct_defaultValue(): T;
struct_getLength(value: T): number;
getMaxLength(): number;
getMinLength(): number;
bytes_validate(data: Uint8Array, start: number, end: number): void;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_getChunkCount(value: T): number;
struct_hashTreeRoot(value: T): Uint8Array;
struct_convertFromJson(data: Json, options?: IJsonOptions): T;
struct_convertToTree(value: T): Tree;
tree_defaultNode(): Node;
tree_defaultValue(): Tree;
tree_getLength(target: Tree): number;
tree_setLength(target: Tree, length: number): void;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
tree_getChunkCount(target: Tree): number;
getChunkDepth(): number;
tree_setProperty(target: Tree, property: number, value: T[number]): boolean;
tree_deleteProperty(target: Tree, property: number): boolean;
tree_pushSingle(target: Tree, value: T[number]): number;
tree_push(target: Tree, ...values: T[number][]): number;
tree_pop(target: Tree): T[number];
hasVariableSerializedLength(): boolean;
getMaxChunkCount(): number;
}

@@ -24,5 +47,26 @@ export declare class CompositeListType<T extends List<object> = List<object>> extends CompositeArrayType<T> {

constructor(options: IListOptions);
isVariableSize(): boolean;
chunkCount(): number;
hasVariableSerializedLength(): boolean;
getMaxChunkCount(): number;
struct_defaultValue(): T;
struct_getLength(value: T): number;
getMaxLength(): number;
getMinLength(): number;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_getChunkCount(value: T): number;
struct_hashTreeRoot(value: T): Uint8Array;
struct_convertFromJson(data: Json, options?: IJsonOptions): T;
tree_defaultNode(): Node;
tree_defaultValue(): Tree;
struct_convertToTree(value: T): Tree;
tree_getLength(target: Tree): number;
tree_setLength(target: Tree, length: number): void;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
tree_getChunkCount(target: Tree): number;
getChunkDepth(): number;
tree_setProperty(target: Tree, property: number, value: Tree): boolean;
tree_deleteProperty(target: Tree, property: number): boolean;
tree_pushSingle(target: Tree, value: Tree): number;
tree_push(target: Tree, ...values: Tree[]): number;
tree_pop(target: Tree): T[number];
}
export {};

@@ -15,4 +15,6 @@ "use strict";

var _backings = require("../../backings");
var _compat = require("../../util/compat");
var _persistentMerkleTree = require("@chainsafe/persistent-merkle-tree");
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

@@ -47,5 +49,2 @@

this.limit = options.limit;
this.structural = new _backings.BasicListStructuralHandler(this);
this.tree = new _backings.BasicListTreeHandler(this);
this.byteArray = new _backings.BasicListByteArrayHandler(this);

@@ -55,7 +54,161 @@ this._typeSymbols.add(LIST_TYPE);

isVariableSize() {
struct_defaultValue() {
return [];
}
struct_getLength(value) {
return value.length;
}
getMaxLength() {
return this.limit;
}
getMinLength() {
return 0;
}
bytes_validate(data, start, end) {
super.bytes_validate(data, start, end);
if (end - start > this.getMaxSerializedLength()) {
throw new Error("Deserialized list length greater than limit");
}
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
return super.struct_deserializeFromBytes(data, start, end);
}
struct_getChunkCount(value) {
return Math.ceil(value.length * this.elementType.struct_getSerializedLength() / 32);
}
struct_hashTreeRoot(value) {
return (0, _compat.mixInLength)(super.struct_hashTreeRoot(value), value.length);
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
struct_convertFromJson(data, options) {
if (!Array.isArray(data)) {
throw new Error("Invalid JSON list: expected an Array");
}
const maxLength = this.limit;
if (data.length > maxLength) {
throw new Error("Invalid JSON list: length ".concat(data.length, " greater than limit ").concat(maxLength));
}
return super.struct_convertFromJson(data);
}
struct_convertToTree(value) {
const tree = super.struct_convertToTree(value);
this.tree_setLength(tree, value.length);
return tree;
}
tree_defaultNode() {
if (!this._defaultNode) {
this._defaultNode = new _persistentMerkleTree.BranchNode((0, _persistentMerkleTree.zeroNode)(super.getChunkDepth()), (0, _persistentMerkleTree.zeroNode)(0));
}
return this._defaultNode;
}
tree_defaultValue() {
return new _persistentMerkleTree.Tree(this.tree_defaultNode());
}
tree_getLength(target) {
return _basic.number32Type.struct_deserializeFromBytes(target.getRoot(BigInt(3)), 0);
}
tree_setLength(target, length) {
const chunk = new Uint8Array(32);
_basic.number32Type.toBytes(length, chunk, 0);
target.setRoot(BigInt(3), chunk);
}
tree_deserializeFromBytes(data, start, end) {
const length = (end - start) / this.elementType.struct_getSerializedLength();
if (!Number.isSafeInteger(length)) {
throw new Error("Deserialized list byte length must be divisible by element size");
}
if (length > this.limit) {
throw new Error("Deserialized list length greater than limit");
}
const value = super.tree_deserializeFromBytes(data, start, end);
this.tree_setLength(value, length);
return value;
}
tree_getChunkCount(target) {
return Math.ceil(this.tree_getLength(target) * this.elementType.struct_getSerializedLength() / 32);
}
getChunkDepth() {
return super.getChunkDepth() + 1;
}
tree_setProperty(target, property, value) {
const length = this.tree_getLength(target);
if (property > length) {
throw new Error("Invalid length index");
} else if (property == length) {
this.tree_pushSingle(target, value);
return true;
} else {
return this.tree_setValueAtIndex(target, property, value);
}
}
tree_deleteProperty(target, property) {
const length = this.tree_getLength(target);
if (property > length) {
throw new Error("Invalid length index");
} else if (property == length) {
this.tree_pop(target);
return true;
} else {
return super.tree_deleteProperty(target, property);
}
}
tree_pushSingle(target, value) {
const length = this.tree_getLength(target);
const expand = this.getChunkIndex(length) != this.getChunkIndex(length + 1);
this.tree_setValueAtIndex(target, length, value, expand);
this.tree_setLength(target, length + 1);
return length + 1;
}
tree_push(target, ...values) {
let newLength;
values.forEach(value => newLength = this.tree_pushSingle(target, value));
return newLength;
}
tree_pop(target) {
const length = this.tree_getLength(target);
const value = this.tree_getProperty(target, length - 1);
super.tree_deleteProperty(target, length - 1);
this.tree_setLength(target, length - 1);
return value;
}
hasVariableSerializedLength() {
return true;
}
chunkCount() {
getMaxChunkCount() {
return Math.ceil(this.limit * this.elementType.size() / 32);

@@ -75,5 +228,2 @@ }

this.limit = options.limit;
this.structural = new _backings.CompositeListStructuralHandler(this);
this.tree = new _backings.CompositeListTreeHandler(this);
this.byteArray = new _backings.CompositeListByteArrayHandler(this);

@@ -83,10 +233,184 @@ this._typeSymbols.add(LIST_TYPE);

isVariableSize() {
hasVariableSerializedLength() {
return true;
}
chunkCount() {
getMaxChunkCount() {
return this.limit;
}
struct_defaultValue() {
return [];
}
struct_getLength(value) {
return value.length;
}
getMaxLength() {
return this.limit;
}
getMinLength() {
return 0;
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
const value = super.struct_deserializeFromBytes(data, start, end);
if (value.length > this.limit) {
throw new Error("Deserialized list length greater than limit: ".concat(value.length, " ").concat(this.limit));
}
return value;
}
struct_getChunkCount(value) {
return value.length;
}
struct_hashTreeRoot(value) {
return (0, _compat.mixInLength)(super.struct_hashTreeRoot(value), value.length);
}
struct_convertFromJson(data, options) {
if (!Array.isArray(data)) {
throw new Error("Invalid JSON list: expected an Array");
}
const maxLength = this.limit;
if (data.length > maxLength) {
throw new Error("Invalid JSON list: length ".concat(data.length, " greater than limit ").concat(maxLength));
}
return super.struct_convertFromJson(data, options);
}
tree_defaultNode() {
if (!this._defaultNode) {
this._defaultNode = new _persistentMerkleTree.BranchNode((0, _persistentMerkleTree.zeroNode)(super.getChunkDepth()), (0, _persistentMerkleTree.zeroNode)(0));
}
return this._defaultNode;
}
tree_defaultValue() {
return new _persistentMerkleTree.Tree(this.tree_defaultNode());
}
struct_convertToTree(value) {
const tree = super.struct_convertToTree(value);
this.tree_setLength(tree, value.length);
return tree;
}
tree_getLength(target) {
return _basic.number32Type.struct_deserializeFromBytes(target.getRoot(BigInt(3)), 0);
}
tree_setLength(target, length) {
const chunk = new Uint8Array(32);
_basic.number32Type.struct_serializeToBytes(length, chunk, 0);
target.setRoot(BigInt(3), chunk);
}
tree_deserializeFromBytes(data, start, end) {
const target = this.tree_defaultValue();
if (this.elementType.hasVariableSerializedLength()) {
const offsets = this.bytes_getVariableOffsets(new Uint8Array(data.buffer, data.byteOffset + start, end - start));
if (offsets.length > this.limit) {
throw new Error("Deserialized list length greater than limit");
}
for (let i = 0; i < offsets.length; i++) {
const [currentOffset, nextOffset] = offsets[i];
this.tree_setSubtreeAtChunkIndex(target, i, this.elementType.tree_deserializeFromBytes(data, start + currentOffset, start + nextOffset));
}
this.tree_setLength(target, offsets.length);
} else {
const elementSize = this.elementType.struct_getSerializedLength(null);
const length = (end - start) / elementSize;
if (!Number.isSafeInteger(length)) {
throw new Error("Deserialized list byte length must be divisible by element size");
}
if (length > this.limit) {
throw new Error("Deserialized list length greater than limit");
}
for (let i = 0; i < length; i++) {
this.tree_setSubtreeAtChunkIndex(target, i, this.elementType.tree_deserializeFromBytes(data, start + i * elementSize, start + (i + 1) * elementSize), true // expand tree as needed
);
}
this.tree_setLength(target, length);
}
return target;
}
tree_getChunkCount(target) {
return this.tree_getLength(target);
}
getChunkDepth() {
return super.getChunkDepth() + 1;
}
tree_setProperty(target, property, value) {
const length = this.tree_getLength(target);
if (property > length) {
throw new Error("Invalid length index");
} else if (property == length) {
this.tree_pushSingle(target, value);
} else {
this.tree_setSubtreeAtChunkIndex(target, property, value);
}
return true;
}
tree_deleteProperty(target, property) {
const length = this.tree_getLength(target);
if (property > length) {
throw new Error("Invalid length index");
} else if (property == length) {
this.tree_pop(target);
return true;
} else {
return super.tree_deleteProperty(target, property);
}
}
tree_pushSingle(target, value) {
const length = this.tree_getLength(target);
this.tree_setSubtreeAtChunkIndex(target, length, value, true);
this.tree_setLength(target, length + 1);
return length + 1;
}
tree_push(target, ...values) {
let newLength;
values.forEach(value => newLength = this.tree_pushSingle(target, value));
return newLength;
}
tree_pop(target) {
const length = this.tree_getLength(target);
const value = this.tree_getProperty(target, length - 1);
this.tree_setSubtreeAtChunkIndex(target, length - 1, new _persistentMerkleTree.Tree((0, _persistentMerkleTree.zeroNode)(0)));
this.tree_setLength(target, length - 1);
return value;
}
}

@@ -93,0 +417,0 @@

import { ByteVectorType } from "./byteVector";
import { CompositeType } from "./abstract";
import { Type } from "../type";
import { CompositeValue } from "../../interface";
/**
* Allow for lazily evaulated expandedType thunk
*/
export interface IRootOptions<T extends object> {
export interface IRootOptions<T extends CompositeValue> {
expandedType: CompositeType<T> | (() => CompositeType<T>);
}
export declare const ROOT_TYPE: unique symbol;
export declare function isRootType<T extends object = object>(type: Type<unknown>): type is RootType<T>;
export declare class RootType<T extends object> extends ByteVectorType {
export declare function isRootType<T extends CompositeValue = CompositeValue>(type: Type<unknown>): type is RootType<T>;
export declare class RootType<T extends CompositeValue> extends ByteVectorType {
_expandedType: CompositeType<T> | (() => CompositeType<T>);

@@ -14,0 +15,0 @@ constructor(options: IRootOptions<T>);

@@ -1,4 +0,5 @@

import { Vector } from "../../interface";
import { Json, Vector } from "../../interface";
import { IArrayOptions, BasicArrayType, CompositeArrayType } from "./array";
import { Type } from "../type";
import { Node, Tree } from "@chainsafe/persistent-merkle-tree";
export interface IVectorOptions extends IArrayOptions {

@@ -17,4 +18,17 @@ length: number;

constructor(options: IVectorOptions);
isVariableSize(): boolean;
chunkCount(): number;
struct_defaultValue(): T;
struct_getLength(value?: T): number;
getMaxLength(): number;
getMinLength(): number;
bytes_validate(data: Uint8Array, start: number, end: number): void;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_assertValidValue(value: unknown): asserts value is T;
struct_convertFromJson(data: Json): T;
tree_defaultNode(): Node;
tree_defaultValue(): Tree;
tree_getLength(target: Tree): number;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
tree_setProperty(target: Tree, property: number, value: T[number]): boolean;
hasVariableSerializedLength(): boolean;
getMaxChunkCount(): number;
}

@@ -24,5 +38,17 @@ export declare class CompositeVectorType<T extends Vector<object> = Vector<object>> extends CompositeArrayType<T> {

constructor(options: IVectorOptions);
isVariableSize(): boolean;
chunkCount(): number;
struct_defaultValue(): T;
struct_getLength(value: T): number;
getMaxLength(): number;
getMinLength(): number;
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T;
struct_assertValidValue(value: unknown): asserts value is T;
struct_convertFromJson(data: Json): T;
tree_defaultNode(): Node;
tree_defaultValue(): Tree;
tree_getLength(target: Tree): number;
tree_deserializeFromBytes(data: Uint8Array, start: number, end: number): Tree;
setProperty(target: Tree, property: number, value: Tree): boolean;
hasVariableSerializedLength(): boolean;
getMaxChunkCount(): number;
}
export {};

@@ -11,4 +11,2 @@ "use strict";

var _backings = require("../../backings");
var _basic = require("../basic");

@@ -18,2 +16,4 @@

var _persistentMerkleTree = require("@chainsafe/persistent-merkle-tree");
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

@@ -49,5 +49,2 @@

this.length = options.length;
this.structural = new _backings.BasicVectorStructuralHandler(this);
this.tree = new _backings.BasicVectorTreeHandler(this);
this.byteArray = new _backings.BasicVectorByteArrayHandler(this);

@@ -57,7 +54,99 @@ this._typeSymbols.add(VECTOR_TYPE);

isVariableSize() {
struct_defaultValue() {
return Array.from({
length: this.length
}, () => {
return this.elementType.struct_defaultValue();
});
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
struct_getLength(value) {
return this.length;
}
getMaxLength() {
return this.length;
}
getMinLength() {
return this.length;
}
bytes_validate(data, start, end) {
super.bytes_validate(data, start, end);
if (end - start !== this.size(null)) {
throw new Error("Incorrect deserialized vector length");
}
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
return super.struct_deserializeFromBytes(data, start, end);
}
struct_assertValidValue(value) {
const actualLength = value.length;
const expectedLength = this.struct_getLength(value);
if (actualLength !== expectedLength) {
throw new Error("Invalid vector length: expected ".concat(expectedLength, ", actual ").concat(actualLength));
}
super.struct_assertValidValue(value);
}
struct_convertFromJson(data) {
if (!Array.isArray(data)) {
throw new Error("Invalid JSON vector: expected an Array");
}
const expectedLength = this.length;
if (data.length !== expectedLength) {
throw new Error("Invalid JSON vector length: expected ".concat(expectedLength, ", actual ").concat(data.length));
}
return super.fromJson(data);
}
tree_defaultNode() {
if (!this._defaultNode) {
this._defaultNode = (0, _persistentMerkleTree.subtreeFillToLength)((0, _persistentMerkleTree.zeroNode)(0), this.getChunkDepth(), this.getMaxChunkCount());
}
return this._defaultNode;
}
tree_defaultValue() {
return new _persistentMerkleTree.Tree(this.tree_defaultNode());
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
tree_getLength(target) {
return this.length;
}
tree_deserializeFromBytes(data, start, end) {
if (end - start !== this.struct_getSerializedLength(null)) {
throw new Error("Incorrect deserialized vector length");
}
return super.tree_deserializeFromBytes(data, start, end);
}
tree_setProperty(target, property, value) {
if (property >= this.tree_getLength(target)) {
throw new Error("Invalid array index");
}
return super.tree_setProperty(target, property, value, false);
}
hasVariableSerializedLength() {
return false;
}
chunkCount() {
getMaxChunkCount() {
return Math.ceil(this.length * this.elementType.size() / 32);

@@ -77,5 +166,2 @@ }

this.length = options.length;
this.structural = new _backings.CompositeVectorStructuralHandler(this);
this.tree = new _backings.CompositeVectorTreeHandler(this);
this.byteArray = new _backings.CompositeVectorByteArrayHandler(this);

@@ -85,10 +171,122 @@ this._typeSymbols.add(VECTOR_TYPE);

isVariableSize() {
return this.elementType.isVariableSize();
struct_defaultValue() {
return Array.from({
length: this.length
}, () => {
return this.elementType.struct_defaultValue();
});
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
struct_getLength(value) {
return this.length;
}
chunkCount() {
getMaxLength() {
return this.length;
}
getMinLength() {
return this.length;
}
struct_deserializeFromBytes(data, start, end) {
this.bytes_validate(data, start, end);
const value = super.struct_deserializeFromBytes(data, start, end);
if (value.length !== this.length) {
throw new Error("Incorrect deserialized vector length");
}
return value;
}
struct_assertValidValue(value) {
const actualLength = value.length;
const expectedLength = this.struct_getLength(value);
if (actualLength !== expectedLength) {
throw new Error("Invalid vector length: expected ".concat(expectedLength, ", actual ").concat(actualLength));
}
super.struct_assertValidValue(value);
}
struct_convertFromJson(data) {
if (!Array.isArray(data)) {
throw new Error("Invalid JSON vector: expected an Array");
}
const expectedLength = this.length;
if (data.length !== expectedLength) {
throw new Error("Invalid JSON vector length: expected ".concat(expectedLength, ", actual ").concat(data.length));
}
return super.struct_convertFromJson(data);
}
tree_defaultNode() {
if (!this._defaultNode) {
this._defaultNode = (0, _persistentMerkleTree.subtreeFillToLength)(this.elementType.tree_defaultNode(), this.getChunkDepth(), this.length);
}
return this._defaultNode;
}
tree_defaultValue() {
return new _persistentMerkleTree.Tree(this.tree_defaultNode());
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
tree_getLength(target) {
return this.length;
}
tree_deserializeFromBytes(data, start, end) {
const target = this.tree_defaultValue();
if (this.elementType.hasVariableSerializedLength()) {
const offsets = this.bytes_getVariableOffsets(new Uint8Array(data.buffer, data.byteOffset + start, end - start));
if (offsets.length !== this.length) {
throw new Error("Incorrect deserialized vector length");
}
for (let i = 0; i < offsets.length; i++) {
const [currentOffset, nextOffset] = offsets[i];
this.tree_setSubtreeAtChunkIndex(target, i, this.elementType.tree_deserializeFromBytes(data, start + currentOffset, start + nextOffset));
}
} else {
const elementSize = this.elementType.struct_getSerializedLength(null);
const length = (end - start) / elementSize;
if (length !== this.length) {
throw new Error("Incorrect deserialized vector length");
}
for (let i = 0; i < length; i++) {
this.tree_setSubtreeAtChunkIndex(target, i, this.elementType.tree_deserializeFromBytes(data, start + i * elementSize, start + (i + 1) * elementSize));
}
}
return target;
}
setProperty(target, property, value) {
if (property >= this.tree_getLength(target)) {
throw new Error("Invalid array index");
}
return super.tree_setProperty(target, property, value, false);
}
hasVariableSerializedLength() {
return this.elementType.hasVariableSerializedLength();
}
getMaxChunkCount() {
return this.length;
}
}

@@ -95,0 +293,0 @@

@@ -22,18 +22,28 @@ import { Json } from "../interface";

constructor();
abstract struct_assertValidValue(value: unknown): asserts value is T;
abstract struct_defaultValue(): T;
abstract struct_clone(value: T): T;
abstract struct_equals(value1: T, value2: T): boolean;
abstract struct_getSerializedLength(value?: T): number;
abstract struct_deserializeFromBytes(data: Uint8Array, start: number, end?: number): T;
abstract struct_serializeToBytes(value: T, output: Uint8Array, offset: number): number;
abstract struct_hashTreeRoot(value: T): Uint8Array;
abstract struct_convertFromJson(data: Json, options?: IJsonOptions): T;
abstract struct_convertToJson(value: T, options?: IJsonOptions): Json;
/**
* Valid value assertion
*/
abstract assertValidValue(value: unknown): asserts value is T;
assertValidValue(value: unknown): asserts value is T;
/**
* Default constructor
*/
abstract defaultValue(): T;
defaultValue(): T;
/**
* Clone / copy
*/
abstract clone(value: T): T;
clone(value: T): T;
/**
* Equality
*/
abstract equals(value1: T, value2: T): boolean;
equals(value1: T, value2: T): boolean;
/**

@@ -44,26 +54,23 @@ * Check if type has a variable number of elements (or subelements)

*/
abstract isVariableSize(): boolean;
abstract hasVariableSerializedLength(): boolean;
/**
* Serialized byte length
*/
abstract size(value?: T): number;
/**
* Maximal serialized byte length
*/
abstract maxSize(): number;
abstract getMaxSerializedLength(): number;
/**
* Minimal serialized byte length
*/
abstract minSize(): number;
abstract getMinSerializedLength(): number;
/**
* Low-level deserialization
* Serialized byte length
*/
size(value?: T): number;
/**
* Low-level deserialization
*/
abstract fromBytes(data: Uint8Array, start: number, end?: number): T;
fromBytes(data: Uint8Array, start: number, end?: number): T;
/**
* Deserialization
*/
abstract deserialize(data: Uint8Array): T;
deserialize(data: Uint8Array): T;
/**

@@ -74,19 +81,19 @@ * Low-level serialization

*/
abstract toBytes(value: T, output: Uint8Array, offset: number): number;
toBytes(value: T, output: Uint8Array, offset: number): number;
/**
* Serialization
*/
abstract serialize(value: T): Uint8Array;
serialize(value: T): Uint8Array;
/**
* Merkleization
*/
abstract hashTreeRoot(value: T): Uint8Array;
hashTreeRoot(value: T): Uint8Array;
/**
* Convert from JSON-serializable object
*/
abstract fromJson(data: Json, options?: IJsonOptions): T;
fromJson(data: Json, options?: IJsonOptions): T;
/**
* Convert to JSON-serializable object
*/
abstract toJson(value: T, options?: IJsonOptions): Json;
toJson(value: T, options?: IJsonOptions): Json;
}

@@ -11,2 +11,6 @@ "use strict";

/* eslint-disable @typescript-eslint/member-ordering */
/* eslint-disable @typescript-eslint/camelcase */
/**

@@ -36,7 +40,108 @@ * Check if `type` is an instance of `typeSymbol` type

}
/**
* Valid value assertion
*/
assertValidValue(value) {
return this.struct_assertValidValue(value);
}
/**
* Default constructor
*/
defaultValue() {
return this.struct_defaultValue();
}
/**
* Clone / copy
*/
clone(value) {
return this.struct_clone(value);
}
/**
* Equality
*/
equals(value1, value2) {
return this.struct_equals(value1, value2);
} // Serialization / Deserialization
/**
* Check if type has a variable number of elements (or subelements)
*
* For basic types, this is always false
*/
/**
* Serialized byte length
*/
size(value) {
return this.struct_getSerializedLength(value);
}
/**
* Low-level deserialization
*/
fromBytes(data, start, end) {
return this.struct_deserializeFromBytes(data, start, end);
}
/**
* Deserialization
*/
deserialize(data) {
return this.fromBytes(data, 0, data.length);
}
/**
* Low-level serialization
*
* Serializes to a pre-allocated Uint8Array
*/
toBytes(value, output, offset) {
return this.struct_serializeToBytes(value, output, offset);
}
/**
* Serialization
*/
serialize(value) {
const output = new Uint8Array(this.size(value));
this.toBytes(value, output, 0);
return output;
}
/**
* Merkleization
*/
hashTreeRoot(value) {
return this.struct_hashTreeRoot(value);
}
/**
* Convert from JSON-serializable object
*/
fromJson(data, options) {
return this.struct_convertFromJson(data, options);
}
/**
* Convert to JSON-serializable object
*/
toJson(value, options) {
return this.struct_convertToJson(value, options);
}
}

@@ -43,0 +148,0 @@

@@ -23,4 +23,6 @@ "use strict";

function mixInLength(root, length) {
return (0, _merkleize2.mixInLength)(Buffer.from(root), length);
const lengthBuf = Buffer.alloc(32);
lengthBuf.writeUIntLE(length, 0, 6);
return hash(root, lengthBuf);
}
//# sourceMappingURL=compat.js.map

@@ -7,3 +7,3 @@ {

"homepage": "https://github.com/chainsafe/ssz",
"version": "0.7.1",
"version": "0.8.0",
"main": "lib/index.js",

@@ -10,0 +10,0 @@ "files": [

@@ -69,3 +69,3 @@ # ssz

// The merkle-tree-backed representation of a Keypair may be created / operated on
const kp2: Keypair = Keypair.tree.defaultValue();
const kp2: TreeBacked<Keypair> = Keypair.defaultTreeBacked();

@@ -72,0 +72,0 @@ // All of the same operations can be performed on tree-backed values

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc