Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sliceFrom to ListCompositeTreeViewDU #366

Merged
merged 9 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion packages/ssz/src/viewDU/listComposite.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Node, treeZeroAfterIndex} from "@chainsafe/persistent-merkle-tree";
import {Node, subtreeFillToContents, treeZeroAfterIndex, zeroNode} from "@chainsafe/persistent-merkle-tree";
import {ByteViews, ValueOf} from "../type/abstract";
import {CompositeType, CompositeView, CompositeViewDU} from "../type/composite";
import {ListCompositeType} from "../view/listComposite";
Expand Down Expand Up @@ -66,6 +66,43 @@ export class ListCompositeTreeViewDU<
return this.type.getViewDU(newRootNode) as this;
}

/**
* Returns a new ListCompositeTreeViewDU instance with the values from `index` to the end of list
*
* ```ts
* const nodes = getChunkNodes()
* return listFromChunkNodes(node.clice(index))
* ```
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
*
* Note: If index === n, returns an empty list of length 0
*
*/
sliceFrom(index: number): this {
// Commit before getting rootNode to ensure all pending data is in the rootNode
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
this.commit();

// If slicing from 0, no slicing is necesary
if (index <= 0) {
return this;
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
}

let newChunksNode;
let newLength;

if (index >= this.nodes.length) {
newChunksNode = zeroNode(this.type.chunkDepth);
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
newLength = 0;
} else {
const nodes = this.nodes.slice(index);
newChunksNode = subtreeFillToContents(nodes, this.type.chunkDepth);
newLength = nodes.length;
}

const newRootNode = this.type.tree_setChunksNode(this._rootNode, newChunksNode, newLength);

return this.type.getViewDU(newRootNode) as this;
}

/**
* Same method to `type/listComposite.ts` leveraging cached nodes.
*/
Expand Down
31 changes: 31 additions & 0 deletions packages/ssz/test/unit/byType/listComposite/tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,34 @@ describe("ListCompositeType.sliceTo", () => {
}
});
});

describe("ListCompositeType.sliceFrom", () => {
it("Slice List at multiple length", () => {
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
const listType = new ListCompositeType(ssz.Root, 1024);
const listView = listType.defaultViewDU();
const listRoots: string[] = [];
const listSerialized: string[] = [];

for (let i = 0; i < 16; i++) {
listView.push(Buffer.alloc(32, 0xf + i));
}

for (let i = 0; i < 16; i++) {
const currentListView = listType.defaultViewDU();

for (let j = i; j < 16; j++) {
currentListView.push(Buffer.alloc(32, 0xf + j));
listSerialized[i] = toHexString(currentListView.serialize());
listRoots[i] = toHexString(currentListView.hashTreeRoot());
}
}

for (let i = -1; i < 16; i++) {
const index = i !== -1 ? i : 0;
const listSlice = listView.sliceFrom(index);
expect(listSlice.length).to.equal(16 - index, `Wrong length at .sliceFrom(${i})`);
expect(toHexString(listSlice.serialize())).equals(listSerialized[index], `Wrong serialize at .sliceFrom(${i})`);
expect(toHexString(listSlice.hashTreeRoot())).equals(listRoots[index], `Wrong root at .sliceFrom(${i})`);
}
});
});
Loading