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

Refactoring: Push(namespace.PrefixedData)->Push(namespace.ID, []byte) #56

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestFuzzProveVerifyNameSpace(t *testing.T) {
for _, ns := range sortedKeys {
leafDataList := nidDataMap[ns]
for _, d := range leafDataList {
err := tree.Push(d)
err := tree.Push(d[:size], d[size:])
if err != nil {
t.Fatalf("error on Push(): %v", err)
}
Expand Down
22 changes: 0 additions & 22 deletions namespace/data.go

This file was deleted.

4 changes: 1 addition & 3 deletions namespace/doc.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
// Package namespace contains the core namespaced data types:
// * PrefixedData represents the leaf data that gets pushed to the NMT (data prefixed with a namespace.ID)
// * IntervalDigest is the result of a namespaced hashing operation (minNs, maxNs, rawRoot).
// Package namespace contains core namespaced data types.
package namespace
14 changes: 13 additions & 1 deletion namespace/id.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package namespace

import "bytes"
import (
"bytes"
"math"
)

// IDMaxSize defines the max. allowed namespace ID size in bytes.
const IDMaxSize = math.MaxUint8

// IDSize is the number of bytes a namespace uses.
// Valid values are in [0,255].
type IDSize uint8

// ID represents a namespace ID.
// It's just augments byte slices with a few convenience methods.
type ID []byte

func (nid ID) Less(other ID) bool {
Expand Down
10 changes: 0 additions & 10 deletions namespace/size.go

This file was deleted.

25 changes: 15 additions & 10 deletions nmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,23 @@ func (n NamespacedMerkleTree) NamespaceSize() namespace.IDSize {
// Returns an error if the namespace ID size of the input
// does not match the tree's NamespaceSize() or the leaves are not pushed in
// order (i.e. lexicographically sorted by namespace ID).
func (n *NamespacedMerkleTree) Push(namespacedData namespace.PrefixedData) error {
nID, err := n.validateAndExtractNamespace(namespacedData)
func (n *NamespacedMerkleTree) Push(nID namespace.ID, data []byte) error {
err := n.validateNamespace(nID)
if err != nil {
return err
}

// TODO(liamsi): this is bad and lazy! We are copying the nid and data here once instead of just
// using the referenced slices we got. Reason is that internally we still treat a leaf as a single slice
// of bytes. We can and should fix this. For now we are living with the copying to have the API updated from
// Push(prefixedData) to Push(nID, data). See: https://github.com/celestiaorg/nmt/issues/55
// We intentionally do the copying here instead of forcing the user to merge (copy) the nid and data
// externally (bad UX).
leafDataCopy := make([]byte, len(nID)+len(data))
copy(leafDataCopy[:len(nID)], nID)
copy(leafDataCopy[len(nID):], data)
// update relevant "caches":
n.leaves = append(n.leaves, namespacedData)
n.leaves = append(n.leaves, leafDataCopy)
n.updateNamespaceRanges()
n.updateMinMaxID(nID)
n.rawRoot = nil
Expand Down Expand Up @@ -328,25 +337,21 @@ func (n *NamespacedMerkleTree) updateNamespaceRanges() {
}
}
}
func (n *NamespacedMerkleTree) validateAndExtractNamespace(ndata namespace.PrefixedData) (namespace.ID, error) {
func (n *NamespacedMerkleTree) validateNamespace(nID namespace.ID) error {
nidSize := int(n.NamespaceSize())
if len(ndata) < nidSize {
return nil, fmt.Errorf("%w: got: %v, want >= %v", ErrMismatchedNamespaceSize, len(ndata), nidSize)
}
nID := namespace.ID(ndata[:n.NamespaceSize()])
// ensure pushed data doesn't have a smaller namespace than the previous one:
curSize := len(n.leaves)
if curSize > 0 {
if nID.Less(n.leaves[curSize-1][:nidSize]) {
return nil, fmt.Errorf(
return fmt.Errorf(
"%w: last namespace: %x, pushed: %x",
ErrInvalidPushOrder,
n.leaves[curSize-1][:nidSize],
nID,
)
}
}
return nID, nil
return nil
}

func (n *NamespacedMerkleTree) updateMinMaxID(id namespace.ID) {
Expand Down
Loading