Skip to content

Commit

Permalink
Fix ListCompositeType.sliceTo(-1) (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
dapplion authored May 31, 2022
1 parent e3782b7 commit 62ae879
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
6 changes: 6 additions & 0 deletions packages/persistent-merkle-tree/src/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,12 @@ export function treeZeroAfterIndex(rootNode: Node, nodesDepth: number, index: nu
// goRight = (N & mask) == mask
// ```

// Degenerate case where tree is zero after a negative index (-1).
// All positive indexes are zero, so the entire tree is zero. Return cached zero node as root.
if (index < 0) {
return zeroNode(nodesDepth);
}

/**
* Contiguous filled stack of parent nodes. It get filled in the first descent
* Indexed by depthi
Expand Down
2 changes: 2 additions & 0 deletions packages/ssz/src/viewDU/listComposite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export class ListCompositeTreeViewDU<
* ```
*
* To achieve it, rebinds the underlying tree zero-ing all nodes right of `index`.
*
* Note: Using index = -1, returns an empty list of length 0.
*/
sliceTo(index: number): this {
// Commit before getting rootNode to ensure all pending data is in the rootNode
Expand Down
18 changes: 13 additions & 5 deletions packages/ssz/test/unit/byType/listComposite/tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,24 @@ describe("ListCompositeType.sliceTo", () => {
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, i + 1));
listRoots.push(toHexString(listView.serialize()));
for (let i = -1; i < 16; i++) {
// Skip first loop to persist empty case
if (i >= 0) {
listView.push(Buffer.alloc(32, 0xf + i)); // Avoid 0 case
}
// Javascript arrays can handle negative indexes (ok for tests)
listSerialized[i] = toHexString(listView.serialize());
listRoots[i] = toHexString(listView.hashTreeRoot());
}

for (let i = 0; i < 16; i++) {
// Start at -1 to test the empty case.
for (let i = -1; i < 16; i++) {
const listSlice = listView.sliceTo(i);
expect(listSlice.length).to.equal(i + 1, `Wrong length at .sliceTo(${i})`);
expect(toHexString(listSlice.serialize())).equals(listRoots[i], `Wrong bytes at .sliceTo(${i})`);
expect(toHexString(listSlice.serialize())).equals(listSerialized[i], `Wrong serialize at .sliceTo(${i})`);
expect(toHexString(listSlice.hashTreeRoot())).equals(listRoots[i], `Wrong root at .sliceTo(${i})`);
}
});
});

0 comments on commit 62ae879

Please sign in to comment.