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

Change Push signature and simplify PrefixedData #27

Merged
merged 3 commits into from
Mar 22, 2021
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
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[:size], d[size:])
err := tree.Push(d)
if err != nil {
t.Fatalf("error on Push(): %v", err)
}
Expand Down
38 changes: 11 additions & 27 deletions namespace/data.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
package namespace

// PrefixedData simply represents a slice of bytes which consists of
// a namespace.ID and raw data.
// The user has to guarantee that the bytes are valid namespace prefixed data.
// Go's type system does not allow enforcing the structure we want:
// [namespaceID, rawData ...], especially as this type does not expect any
// particular size for the namespace.
type PrefixedData []byte

// PrefixedData8 like PrefixedData is just a slice of bytes.
// It assumes that the slice it represents is at least 8 bytes.
// This assumption is not enforced by the type system though.
type PrefixedData8 []byte

func (d PrefixedData8) NamespaceID() ID {
Expand All @@ -9,30 +20,3 @@ func (d PrefixedData8) NamespaceID() ID {
func (d PrefixedData8) Data() []byte {
return d[8:]
}

type PrefixedData struct {
namespaceLen IDSize
prefixedData []byte
}

func (n PrefixedData) NamespaceID() ID {
return n.prefixedData[:n.namespaceLen]
}

func (n PrefixedData) Data() []byte {
return n.prefixedData[n.namespaceLen:]
}

func NewPrefixedData(namespaceLen IDSize, prefixedData []byte) PrefixedData {
return PrefixedData{
namespaceLen: namespaceLen,
prefixedData: prefixedData,
}
}

func PrefixedDataFrom(nID ID, data []byte) PrefixedData {
return PrefixedData{
namespaceLen: nID.Size(),
prefixedData: append(nID, data...),
}
}
27 changes: 14 additions & 13 deletions nmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,16 +246,16 @@ 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(id namespace.ID, data []byte) error {
err := n.validateNamespace(id)
func (n *NamespacedMerkleTree) Push(namespacedData namespace.PrefixedData) error {
nID, err := n.validateAndExtractNamespace(namespacedData)
if err != nil {
return err
}
leafData := append(id, data...)

// update relevant "caches":
n.leaves = append(n.leaves, leafData)
n.leaves = append(n.leaves, namespacedData)
n.updateNamespaceRanges()
n.updateMinMaxID(id)
n.updateMinMaxID(nID)
return nil
}

Expand Down Expand Up @@ -321,24 +321,25 @@ func (n *NamespacedMerkleTree) updateNamespaceRanges() {
}
}
}
func (n *NamespacedMerkleTree) validateNamespace(id namespace.ID) error {
nidSize := n.treeHasher.NamespaceSize()
if id.Size() != nidSize {
return fmt.Errorf("%w: got: %v, want: %v", ErrMismatchedNamespaceSize, id.Size(), nidSize)
func (n *NamespacedMerkleTree) validateAndExtractNamespace(ndata namespace.PrefixedData) (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 id.Less(n.leaves[curSize-1][:nidSize]) {
return fmt.Errorf(
if nID.Less(n.leaves[curSize-1][:nidSize]) {
return nil, fmt.Errorf(
"%w: last namespace: %x, pushed: %x",
ErrInvalidPushOrder,
n.leaves[curSize-1][:nidSize],
id,
nID,
)
}
}
return nil
return nID, nil
}

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