Skip to content

Commit c616b55

Browse files
committed
feat: implement ViewDU.batchHashTreeRoot, merge PR #392
2 parents aa7ebfb + a6191d4 commit c616b55

File tree

17 files changed

+723
-118
lines changed

17 files changed

+723
-118
lines changed

packages/ssz/src/type/arrayBasic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
getNodesAtDepth,
66
packedNodeRootsToBytes,
77
packedRootsBytesToNode,
8-
levelAtIndex,
98
HashComputationLevel,
9+
levelAtIndex,
1010
} from "@chainsafe/persistent-merkle-tree";
1111
import {Type, ValueOf, ByteViews} from "./abstract";
1212
import {BasicType} from "./basic";

packages/ssz/src/type/bitArray.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {concatGindices, Gindex, HashComputationLevel, Node, toGindex, Tree} from "@chainsafe/persistent-merkle-tree";
1+
import {concatGindices, Gindex, Node, toGindex, Tree, HashComputationLevel} from "@chainsafe/persistent-merkle-tree";
22
import {fromHexString, toHexString, byteArrayEquals} from "../util/byteArray";
33
import {CompositeType, LENGTH_GINDEX} from "./composite";
44
import {BitArray} from "../value/bitArray";

packages/ssz/src/type/byteArray.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import {concatGindices, Gindex, Node, toGindex, Tree} from "@chainsafe/persistent-merkle-tree";
1+
import {
2+
concatGindices,
3+
Gindex,
4+
Node,
5+
toGindex,
6+
Tree,
7+
HashComputationLevel,
8+
getHashComputations,
9+
} from "@chainsafe/persistent-merkle-tree";
210
import {fromHexString, toHexString, byteArrayEquals} from "../util/byteArray";
311
import {ByteViews} from "./abstract";
412
import {CompositeType, LENGTH_GINDEX} from "./composite";
@@ -36,12 +44,16 @@ export abstract class ByteArrayType extends CompositeType<ByteArray, ByteArray,
3644
return this.commitViewDU(view);
3745
}
3846

39-
// TODO - batch
40-
commitViewDU(view: ByteArray): Node {
47+
// there is no respective ViewDU for this type
48+
commitViewDU(view: ByteArray, hcOffset = 0, hcByLevel: HashComputationLevel[] | null = null): Node {
4149
const uint8Array = new Uint8Array(this.value_serializedSize(view));
4250
const dataView = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);
4351
this.value_serializeToBytes({uint8Array, dataView}, 0, view);
44-
return this.tree_deserializeFromBytes({uint8Array, dataView}, 0, uint8Array.length);
52+
const node = this.tree_deserializeFromBytes({uint8Array, dataView}, 0, uint8Array.length);
53+
if (hcByLevel !== null && node.h0 === null) {
54+
getHashComputations(node, hcOffset, hcByLevel);
55+
}
56+
return node;
4557
}
4658

4759
cacheOfViewDU(): unknown {

packages/ssz/src/type/optional.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import {concatGindices, Gindex, merkleizeInto, Node, Tree, zeroNode} from "@chainsafe/persistent-merkle-tree";
1+
import {
2+
concatGindices,
3+
Gindex,
4+
merkleizeInto,
5+
Node,
6+
Tree,
7+
zeroNode,
8+
getHashComputations,
9+
HashComputationLevel,
10+
} from "@chainsafe/persistent-merkle-tree";
211
import {Require} from "../util/types";
312
import {namedClass} from "../util/named";
413
import {Type, ByteViews, JsonPath, JsonPathProp} from "./abstract";
@@ -81,9 +90,12 @@ export class OptionalType<ElementType extends Type<unknown>> extends CompositeTy
8190
}
8291

8392
// TODO add an OptionalViewDU
84-
// TODO - batch
85-
commitViewDU(view: ValueOfType<ElementType>): Node {
86-
return this.value_toTree(view);
93+
commitViewDU(view: ValueOfType<ElementType>, hcOffset = 0, hcByLevel: HashComputationLevel[] | null = null): Node {
94+
const node = this.value_toTree(view);
95+
if (hcByLevel !== null && node.h0 === null) {
96+
getHashComputations(node, hcOffset, hcByLevel);
97+
}
98+
return node;
8799
}
88100

89101
// TODO add an OptionalViewDU

packages/ssz/src/type/union.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import {concatGindices, getNode, Gindex, Node, Tree, merkleizeInto} from "@chainsafe/persistent-merkle-tree";
1+
import {
2+
concatGindices,
3+
getNode,
4+
Gindex,
5+
Node,
6+
Tree,
7+
merkleizeInto,
8+
getHashComputations,
9+
HashComputationLevel,
10+
} from "@chainsafe/persistent-merkle-tree";
211
import {Require} from "../util/types";
312
import {namedClass} from "../util/named";
413
import {Type, ByteViews} from "./abstract";
@@ -112,9 +121,12 @@ export class UnionType<Types extends Type<unknown>[]> extends CompositeType<
112121
return this.value_toTree(view);
113122
}
114123

115-
// TODO - batch
116-
commitViewDU(view: ValueOfTypes<Types>): Node {
117-
return this.value_toTree(view);
124+
commitViewDU(view: ValueOfTypes<Types>, hcOffset = 0, hcByLevel: HashComputationLevel[] | null = null): Node {
125+
const node = this.value_toTree(view);
126+
if (hcByLevel !== null && node.h0 === null) {
127+
getHashComputations(node, hcOffset, hcByLevel);
128+
}
129+
return node;
118130
}
119131

120132
value_serializedSize(value: ValueOfTypes<Types>): number {

packages/ssz/src/type/vectorComposite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {HashComputationLevel, Node, Tree} from "@chainsafe/persistent-merkle-tree";
1+
import {Node, Tree, HashComputationLevel} from "@chainsafe/persistent-merkle-tree";
22
import {maxChunksToDepth} from "../util/merkleize";
33
import {Require} from "../util/types";
44
import {namedClass} from "../util/named";

packages/ssz/src/view/arrayBasic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {getNodesAtDepth, HashComputationLevel, LeafNode, Node, Tree} from "@chainsafe/persistent-merkle-tree";
1+
import {getNodesAtDepth, LeafNode, Node, Tree, HashComputationLevel} from "@chainsafe/persistent-merkle-tree";
22
import {ValueOf} from "../type/abstract";
33
import {BasicType} from "../type/basic";
44
import {CompositeType} from "../type/composite";

packages/ssz/src/view/arrayComposite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {getNodesAtDepth, HashComputationLevel, Node, toGindexBitstring, Tree} from "@chainsafe/persistent-merkle-tree";
1+
import {getNodesAtDepth, Node, toGindexBitstring, Tree, HashComputationLevel} from "@chainsafe/persistent-merkle-tree";
22
import {ValueOf} from "../type/abstract";
33
import {CompositeType, CompositeView, CompositeViewDU} from "../type/composite";
44
import {TreeView} from "./abstract";

packages/ssz/src/viewDU/abstract.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export abstract class TreeViewDU<T extends CompositeType<unknown, unknown, unkno
6565

6666
/**
6767
* The same to hashTreeRoot() but with batch hash computation.
68-
* Consumer can provide a HashComputationGroup() to save memory allocation.
68+
* Consumer can allocate and reuse a HashComputationGroup() if needed.
6969
*/
7070
batchHashTreeRoot(hcGroup: HashComputationGroup = new HashComputationGroup()): Uint8Array {
7171
// in ethereum consensus, the only type goes with TVDU is BeaconState and it's really more efficient to hash the tree in batch
@@ -91,7 +91,7 @@ export abstract class TreeViewDU<T extends CompositeType<unknown, unknown, unkno
9191
/**
9292
* Serialize view to binary data.
9393
* Commits any pending changes before computing the root.
94-
* Warning: this calls commit() which evict all pending HashComputations. Consider calling hashTreeRoot() before this
94+
* This calls commit() which evict all pending HashComputations. Consider calling hashTreeRoot() before this
9595
*/
9696
serialize(): Uint8Array {
9797
this.commit();

packages/ssz/src/viewDU/containerNodeStruct.ts

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Node} from "@chainsafe/persistent-merkle-tree";
1+
import {Node, HashComputationLevel} from "@chainsafe/persistent-merkle-tree";
22
import {Type, ValueOf} from "../type/abstract";
33
import {isCompositeType} from "../type/composite";
44
import {BranchNodeStruct} from "../branchNodeStruct";
@@ -32,35 +32,22 @@ export class ContainerNodeStructTreeViewDU<Fields extends Record<string, Type<un
3232
}
3333

3434
/**
35-
* This ViewDU does not support batch hash by default so we need to compute root immediately.
36-
* Otherwise consumers may call commit() multiple times and not able to compute hashTreeRoot().
35+
* There are 2 cases:
36+
* - normal commit() or hashTreeRoot(): hcByLevel is null, no need to compute root
37+
* - batchHashTreeRoot(): hcByLevel is not null, need to compute root because this does not support HashComputation
3738
*/
38-
commit(): void {
39-
if (this.valueChanged === null) {
40-
this._rootNode.rootHashObject;
41-
return;
42-
}
43-
44-
const value = this.valueChanged;
45-
this.valueChanged = null;
46-
47-
this._rootNode = this.type.value_toTree(value) as BranchNodeStruct<ValueOfFields<Fields>>;
48-
this._rootNode.rootHashObject;
49-
}
39+
commit(_?: number, hcByLevel: HashComputationLevel[] | null = null): void {
40+
if (this.valueChanged !== null) {
41+
const value = this.valueChanged;
42+
this.valueChanged = null;
5043

51-
/**
52-
* Same to commit() without hash, allow to do the batch hash at consumer side, like in ListValidatorViewDU
53-
* of ethereum consensus node.
54-
*/
55-
commitNoHash(): void {
56-
if (this.valueChanged === null) {
57-
return;
44+
this._rootNode = this.type.value_toTree(value) as BranchNodeStruct<ValueOfFields<Fields>>;
5845
}
5946

60-
const value = this.valueChanged;
61-
this.valueChanged = null;
62-
63-
this._rootNode = this.type.value_toTree(value) as BranchNodeStruct<ValueOfFields<Fields>>;
47+
if (this._rootNode.h0 === null && hcByLevel !== null) {
48+
// consumer is batchHashTreeRoot()
49+
this._rootNode.rootHashObject;
50+
}
6451
}
6552

6653
protected clearCache(): void {

0 commit comments

Comments
 (0)