Skip to content

Commit

Permalink
feat!: resolves output inconsistencies when making multiple calls to …
Browse files Browse the repository at this point in the history
…the EmptyRoot (#197)

## Overview
Closes #196 

## Checklist

- [x] New and updated code has appropriate documentation
- [x] New and updated code has new and/or updated testing
- [x] Required CI checks are passing
- [x] Visual proof for any user facing features like CLI or
documentation updates
- [x] Linked issues closed with keywords
  • Loading branch information
staheri14 committed May 16, 2023
1 parent eabb595 commit 6e416c1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ func (n *Hasher) BlockSize() int {
}

func (n *Hasher) EmptyRoot() []byte {
n.baseHasher.Reset()
emptyNs := bytes.Repeat([]byte{0}, int(n.NamespaceLen))
h := n.baseHasher.Sum(nil)
digest := append(append(emptyNs, emptyNs...), h...)
Expand Down
17 changes: 17 additions & 0 deletions hasher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -947,3 +947,20 @@ func TestComputeNsRange(t *testing.T) {
assert.True(t, bytes.Equal(tc.expectedMaxNs, maxNs))
}
}

// TestEmptyRoot ensures that the empty root is always the same, under the same configuration, regardless of the state of the Hasher.
func TestEmptyRoot(t *testing.T) {
nIDSzie := 1
ignoreMaxNS := true

hasher := NewNmtHasher(sha256.New(), namespace.IDSize(nIDSzie), ignoreMaxNS)
expectedEmptyRoot := hasher.EmptyRoot()

// perform some operation with the hasher
_, err := hasher.HashNode(createByteSlice(hasher.Size(), 1), createByteSlice(hasher.Size(), 1))
assert.NoError(t, err)
gotEmptyRoot := hasher.EmptyRoot()

// the empty root should be the same before and after the operation
assert.True(t, bytes.Equal(gotEmptyRoot, expectedEmptyRoot))
}
25 changes: 25 additions & 0 deletions nmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1130,3 +1130,28 @@ func TestProveNamespace_MaxNamespace(t *testing.T) {
})
}
}

// TestEmptyRoot_NMT tests that the empty root of a tree is the same as the empty root of a hasher with the same configuration.
func TestEmptyRoot_NMT(t *testing.T) {
nIDSzie := 1
ignoreMaxNS := true
nIDList := []byte{1, 2, 3, 4}

// create a nmt using the above configs
tree := New(sha256.New(), NamespaceIDSize(nIDSzie), IgnoreMaxNamespace(ignoreMaxNS))
for i, nid := range nIDList {
namespace := bytes.Repeat([]byte{nid}, nIDSzie)
d := append(namespace, []byte(fmt.Sprintf("leaf_%d", i))...)
if err := tree.Push(d); err != nil {
panic(fmt.Sprintf("unexpected error: %v", err))
}
}
// calculate the empty root by accessing the `Hasher` field of the tree
expectedEmptyRoot := tree.treeHasher.EmptyRoot()

// create a hasher identical to the one used for the tree
hasher := NewNmtHasher(sha256.New(), namespace.IDSize(nIDSzie), ignoreMaxNS)
gotEmptyRoot := hasher.EmptyRoot()

assert.True(t, bytes.Equal(gotEmptyRoot, expectedEmptyRoot))
}
2 changes: 1 addition & 1 deletion proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ func TestVerifyNamespace_EmptyProof(t *testing.T) {
invalidEmptyProof.end = 0

// root of an empty tree
hasher := sha256.New()
emptyRoot := tree.treeHasher.EmptyRoot()
hasher := tree.treeHasher.baseHasher

type args struct {
proof Proof
Expand Down

0 comments on commit 6e416c1

Please sign in to comment.