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

Reworded explanation of calculating namespace when IgnoreMaxNamespace is set #134

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
14 changes: 8 additions & 6 deletions docs/nmt-lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,18 @@ idSize := tree.NamespaceSize() // outputs 1

### Ignore Max Namespace

If the NMT is configured with `IgnoreMaxNamespace` set to true, then the calculation of the namespace ID range of non-leaf nodes in the [namespace hash function](./spec/nmt.md#namespaced-hash) will change slightly.
That is, when determining the upper limit of the namespace ID range for a tree node `n`, with children `l` and `r`, the maximum possible namespace ID, equivalent to `NamespaceIDSize()` bytes of `0xFF`, or `2^NamespaceIDSize()-1`,
should be omitted if feasible (in the preceding code example with the ID size of `1` byte, the maximum possible namespace ID would be `0xFF`).
This is achieved by taking the maximum value among the namespace IDs available in the range of node's left and right children (i.e., `n.maxNs = max(l.minNs, l.maxNs , r.minNs, r.maxNs))`, which is not equal to the maximum possible namespace ID value.
If such a namespace ID does not exist, the `maxNs` is calculated as normal, i.e., `n.maxNs = max(l.maxNs , r.maxNs)`.
If the NMT is configured with `IgnoreMaxNamespace` set to true (the flag is explained [here](#nmt-initialization-and-configuration)), then the calculation of the namespace ID range of non-leaf nodes in the [namespace hash function](./spec/nmt.md#namespaced-hash) will change slightly.
That is, when determining the upper limit of the namespace ID range for a tree node, the maximum possible namespace `maxPossibleNamespace` should not be taken into account.
(In the preceding code example with the ID size of `1` byte, the value of `maxPossibleNamespace` is $2^8-1 = 0xFF$.)

Concretely, for a node `n` with children `l` and `r`, the namespace ID is the largest namespace value from `l` and `r` smaller than `maxPossibleNamespace`, if such a namespace ID exists.
Otherwise, if all candidate values are equal to `maxPossibleNamespace`, the namespace ID of `n` is set to `maxPossibleNamespace`.
Precisely, if a set `C` $= \bigl \lbrace$ `ns` $\in \lbrace$`l.minNs`, `l.maxNs`, `r.minNs`, `r.maxNs` $\rbrace:$ `ns` $<$ `maxPossibleNamespace` $\bigr \rbrace$ is not empty, `n.maxNs = max(C)`. If `C` is empty, `n.maxNs = maxPossibleNamespace`.

## Add Leaves

Data items are added to the tree using the `Push` method.
Data items should be prefixed with namespaces of size set out for the NMT (i.e., `tree.NamespaceSize()`) and added in ascending order of their namespace IDs to avoid errors during the `Push` process.
Data items should be prefixed with namespaces of size set out for the NMT (i.e., `tree.NamespaceSize()`) and added in ascending order of their namespace IDs to avoid errors during the `Push` process.
Non-compliance with either of these requirements cause `Push` to fail.

```go
Expand Down
10 changes: 4 additions & 6 deletions hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,10 @@ func (n *Hasher) ValidateNodes(left, right []byte) error {
// is set to true, the calculation of the namespace ID range of the node
// slightly changes. In this case, when setting the upper range, the maximum
// possible namespace ID (i.e., 2^NamespaceIDSize-1) should be ignored if
// possible. This is achieved by taking the maximum value among the namespace
// IDs available in the range of its left and right children (i.e.,
// max(left.minNID, left.maxNID , right.minNID, right.maxNID)), which is not
// equal to the maximum possible namespace ID value. If such a namespace ID does
// not exist, the maximum NID is calculated as normal, i.e., "res.maxNID =
// max(left.maxNID , right.maxNID).
// possible. This is achieved by taking the maximum value among only those namespace
// IDs available in the range of its left and right children that are not
// equal to the maximum possible namespace ID value. If all the namespace IDs are equal
// to the maximum possible value, then the maximum possible value is used.
func (n *Hasher) HashNode(left, right []byte) []byte {
h := n.baseHasher
h.Reset()
Expand Down