Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export function getGeneralizedIndex(type: FullSSZType, path: Path): GeneralizedIndex {
let root = 1n;
for (const p of path) {
assert(!isBasicType(type));
if (p === "__len__") {
assert(isListType(type));
return root * 2n + 1n;
} else {
if (isListType(type)) {
root *= 2n; // bit for length mix in
}
const [pos] = getItemPosition(type, p);
root = root * nextPowerOf2(BigInt(chunkCount(type))) + BigInt(pos);
type = getElementType(type, p);
}
}
return root;
}
case Type.bitList:
value = value as BitList;
return mixInLength(
merkleize(chunkify(Buffer.from(value.toBitfield())), chunkCount(type)),
value.bitLength
);
case Type.byteList:
value = value as Bytes;
return mixInLength(
merkleize(pack([value], type), chunkCount(type)),
value.length
);
case Type.list:
value = value as SerializableArray;
elementType = type.elementType;
if (isBasicType(elementType)) {
return mixInLength(
merkleize(pack(value, elementType), chunkCount(type)),
value.length
);
} else {
return mixInLength(
merkleize(value.map((v) => _hashTreeRoot(v, elementType)), type.maxLength),
value.length
);
}
case Type.vector:
value = value as SerializableArray;
elementType = type.elementType;
if (isBasicType(elementType)) {
return merkleize(pack(value, elementType));
} else {
export function itemLength(type: FullSSZType): number {
if (isBasicType(type)) {
return fixedSize(type);
} else {
return 32;
}
}
function _getPaths(type: FullSSZType, index: GeneralizedIndex, pathIndices: GeneralizedIndex[], currentIndex: GeneralizedIndex, currentPath: Path): Path[] {
assert(!isBasicType(type));
const prevIndex = currentIndex;
const fullChunkCount = nextPowerOf2(BigInt(chunkCount(type)));
if (type.type === Type.container) {
currentIndex *= fullChunkCount;
for (const [fieldName, fieldType] of type.fields) {
const p = [...currentPath, fieldName];
const fieldIndex = currentIndex + BigInt(getItemPosition(type, fieldName)[0]);
if (fieldIndex === index) {
return [p];
}
if (pathIndices.includes(fieldIndex)) {
return _getPaths(fieldType, index, pathIndices, fieldIndex, p);
}
}
throw new Error("no valid paths");
} else {
elementType = type.elementType;
if (isBasicType(elementType)) {
return mixInLength(
merkleize(pack(value, elementType), chunkCount(type)),
value.length
);
} else {
return mixInLength(
merkleize(value.map((v) => _hashTreeRoot(v, elementType)), type.maxLength),
value.length
);
}
case Type.vector:
value = value as SerializableArray;
elementType = type.elementType;
if (isBasicType(elementType)) {
return merkleize(pack(value, elementType));
} else {
return merkleize(value.map((v) => _hashTreeRoot(v, elementType)));
}
case Type.container:
type = type as ContainerType;
return merkleize(
type.fields.map(([fieldName, fieldType]) =>
_hashTreeRoot((value as SerializableObject)[fieldName], fieldType)));
}
}
pathIndexDelta += 1;
if (currentIndex + 1n === index) {
return [[...currentPath, "__len__"]];
}
}
currentIndex *= fullChunkCount;
const prevPathIndex = pathIndices.indexOf(prevIndex);
const currentPathIndex = pathIndices[prevPathIndex - pathIndexDelta];
const maxIndex = currentIndex + BigInt(getItemPosition(type, maxLength(type as ArrayType))[0]);
if (maxIndex < currentPathIndex) {
throw new Error("no valid paths");
}
const firstMatchedIndex = Number(currentPathIndex - currentIndex);
const elementType = getElementType(type, firstMatchedIndex);
const elementItemLength = itemLength(elementType);
if (isBasicType(elementType)) {
return Array.from({length: Math.floor(32 / elementItemLength)}, (_, i) => firstMatchedIndex + i)
.map((i) => ([...currentPath, i]));
} else {
const elementIndex = currentIndex + BigInt(getItemPosition(type, firstMatchedIndex)[0]);
const path = [...currentPath, firstMatchedIndex];
if (elementIndex === index) {
return [path];
}
return _getPaths(elementType, index, pathIndices, elementIndex, path);
}
}
}