diff --git a/hasher.go b/hasher.go index f12c92b..5dd6470 100644 --- a/hasher.go +++ b/hasher.go @@ -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...) diff --git a/hasher_test.go b/hasher_test.go index e884752..8227ed3 100644 --- a/hasher_test.go +++ b/hasher_test.go @@ -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)) +} diff --git a/nmt_test.go b/nmt_test.go index a184a00..10c4916 100644 --- a/nmt_test.go +++ b/nmt_test.go @@ -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)) +} diff --git a/proof_test.go b/proof_test.go index 7cf6113..62d5a79 100644 --- a/proof_test.go +++ b/proof_test.go @@ -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