-
Notifications
You must be signed in to change notification settings - Fork 43
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
feat: add support for subtree root verification #260
Changes from 11 commits
51df389
4daae42
4ba85fe
12b62f1
ad2f71d
82d1886
cff80b2
47d2113
661d059
a81b748
a68a69f
9d92a94
12ec563
3ad98af
70bc2b0
a580bac
680faca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -862,6 +862,20 @@ func exampleNMT(nidSize int, ignoreMaxNamespace bool, leavesNIDs ...byte) *Names | |
return tree | ||
} | ||
|
||
// exampleNMT2 Replica of exampleNMT except that it uses the namespace IDs in the | ||
// leaves instead of the index. | ||
func exampleNMT2(nidSize int, ignoreMaxNamespace bool, leavesNIDs ...byte) *NamespacedMerkleTree { | ||
rach-id marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tree := New(sha256.New(), NamespaceIDSize(nidSize), IgnoreMaxNamespace(ignoreMaxNamespace)) | ||
for _, nid := range leavesNIDs { | ||
namespace := bytes.Repeat([]byte{nid}, nidSize) | ||
d := append(namespace, []byte(fmt.Sprintf("leaf_%d", nid))...) | ||
if err := tree.Push(d); err != nil { | ||
panic(fmt.Sprintf("unexpected error: %v", err)) | ||
} | ||
} | ||
return tree | ||
} | ||
rach-id marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func swap(slice [][]byte, i int, j int) { | ||
temp := slice[i] | ||
slice[i] = slice[j] | ||
|
@@ -1175,3 +1189,134 @@ func TestForcedOutOfOrderNamespacedMerkleTree(t *testing.T) { | |
assert.NoError(t, err) | ||
} | ||
} | ||
|
||
func TestComputeSubtreeRoot(t *testing.T) { | ||
n := exampleNMT2(1, true, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) | ||
tests := []struct { | ||
start, end int | ||
tree *NamespacedMerkleTree | ||
expectedRoot []byte | ||
expectError bool | ||
}{ | ||
{ | ||
start: 0, | ||
end: 16, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
root, err := n.Root() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This updates the state of the original tree
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's the problem with updating the original tree with a root in a test? that would make the other tests not recalculate it which is good, no? |
||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ | ||
start: 0, | ||
end: 8, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
// because the root of the range [0,8) coincides with the root of this tree | ||
root, err := exampleNMT2(1, true, 0, 1, 2, 3, 4, 5, 6, 7).Root() | ||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ | ||
start: 8, | ||
end: 16, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
// because the root of the range [8,16) coincides with the root of this tree | ||
root, err := exampleNMT2(1, true, 8, 9, 10, 11, 12, 13, 14, 15).Root() | ||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ | ||
start: 8, | ||
end: 12, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
// because the root of the range [8,12) coincides with the root of this tree | ||
root, err := exampleNMT2(1, true, 8, 9, 10, 11).Root() | ||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ | ||
start: 4, | ||
end: 8, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
// because the root of the range [4,8) coincides with the root of this tree | ||
root, err := exampleNMT2(1, true, 4, 5, 6, 7).Root() | ||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ | ||
start: 4, | ||
end: 6, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
// because the root of the range [4,6) coincides with the root of this tree | ||
root, err := exampleNMT2(1, true, 4, 5).Root() | ||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ | ||
start: 4, | ||
end: 5, | ||
tree: n, | ||
expectedRoot: func() []byte { | ||
// because the root of the range [4,5) coincides with the root of this tree | ||
root, err := exampleNMT2(1, true, 4).Root() | ||
require.NoError(t, err) | ||
return root | ||
}(), | ||
}, | ||
{ // doesn't correctly reference an inner node | ||
start: 2, | ||
end: 6, | ||
tree: n, | ||
expectError: true, | ||
}, | ||
{ | ||
start: -1, // invalid start | ||
end: 4, | ||
tree: n, | ||
expectError: true, | ||
}, | ||
{ | ||
start: 4, | ||
end: 4, // start == end | ||
tree: n, | ||
expectError: true, | ||
}, | ||
{ | ||
start: 5, // start >= end | ||
end: 4, | ||
tree: n, | ||
expectError: true, | ||
}, | ||
{ | ||
start: 0, | ||
end: 16, | ||
tree: func() *NamespacedMerkleTree { | ||
return exampleNMT2(1, true, 0, 1, 2, 3, 4) // tree leaves are not a power of 2 | ||
}(), | ||
expectError: true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason that this test case errors out is that the the range of the proof is larger than the size of the tree, hence, the comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. depends on: #260 (comment) |
||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(fmt.Sprintf("treeSize=%d,start=%d,end=%d", tt.tree.Size(), tt.start, tt.end), func(t *testing.T) { | ||
root, err := tt.tree.ComputeSubtreeRoot(tt.start, tt.end) | ||
if tt.expectError { | ||
assert.Error(t, err) | ||
} else { | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.expectedRoot, root) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This exports the LeafRange to be used downstream