-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
[Enhancement] Add Merkle Sum tree functionality (SMT Wrapper) #13
Conversation
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Co-authored-by: Daniel Olshansky <olshansky.daniel@gmail.com>
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #13 +/- ##
==========================================
+ Coverage 84.53% 86.78% +2.25%
==========================================
Files 8 8
Lines 776 984 +208
==========================================
+ Hits 656 854 +198
- Misses 85 94 +9
- Partials 35 36 +1
☔ View full report in Codecov by Sentry. |
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.
smst_testutil.go
Outdated
// otherwise. | ||
func (smst *SMSTWithStorage) Has(key []byte) (bool, error) { | ||
val, sum, err := smst.GetValueSum(key) | ||
return !bytes.Equal(defaultValue, val) || sum != 0, err |
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.
Shouldn't this be not default AND sum != 0
?
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.
!(defaultValue && sum == 0) == !defaultValue || sum != 0 (de morgans law)?
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.
@Olshansk Looking into this more from this example we have the following current functionality:
package main
import (
"crypto/sha256"
"fmt"
"github.com/pokt-network/smt"
)
func main() {
nodeStore := smt.NewSimpleMap()
tree := smt.NewSparseMerkleSumTree(nodeStore, sha256.New())
tree.Update([]byte("key"), []byte(nil), 5)
tree.Update([]byte("key2"), []byte("val2"), 5)
tree.Update([]byte("key3"), []byte("val3"), 5)
tree.Update([]byte("key4"), []byte("val4"), 5)
root := tree.Root()
proof, err := tree.Prove([]byte("key"))
if err != nil {
panic(err)
}
if valid := smt.VerifySumProof(proof, root, []byte("key"), nil, 5, tree.Spec()); valid { // valid
fmt.Println("valid")
} else {
fmt.Println("invalid")
}
nodeStore2 := smt.NewSimpleMap()
tree2 := smt.NewSparseMerkleTree(nodeStore2, sha256.New())
tree2.Update([]byte("key"), []byte(nil))
tree2.Update([]byte("key2"), []byte("val2"))
tree2.Update([]byte("key3"), []byte("val3"))
tree2.Update([]byte("key4"), []byte("val4"))
root2 := tree2.Root()
proof2, err := tree2.Prove([]byte("key"))
if err != nil {
panic(err)
}
if valid := smt.VerifyProof(proof2, root2, []byte("key"), nil, tree2.Spec()); valid { // invalid
fmt.Println("valid")
} else {
fmt.Println("invalid")
}
}
This makes me think that although we can set a nil
value in both trees it will still be a placeholder. For the SMST this is true ONLY if we do not give it a sum. This aligns with the check in the Has
function as if either the sum or the value are set the key is in the tree and is not a placeholder
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.
if either the sum or the value are set the key is in the tree and is not a placeholder
I feel like this implies that we can set a value to be empty (i.e. the placeholder) with a non-zero weight/sum. I can potentially see arguments for it, but feel like it creates room for error/confusion.
In your example above, what I'm seeing is:
- Empty key with weight -> valid proof
- Empty key w/o weight -> invalid proof
- Empty key with weight -> has=True
- Empty key w/o weight -> has=False
I'm open to be swayed in the other direction, but I think that empty (i.e. placeholder) leaves should not be able to have a weight.
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.
@Olshansk I think we should allow ppl to set nil
keys as they exist anyway, setting a key to nil
is basically a noop, it does change the tree but the key is still a placeholder and this doesn't "count" as being in the tree. When we add a weight suddenly it does count as being in the tree as its not the default value anymore.
With this in mind I think the current functionality is correct. Weird edge case that nobody will probably utilise but I think the logic is sound. If the key is default in every then its not in the tree (placeholder) but if it has a value and 0 sum - in the tree, if it has no value but has a sum - in the tree. Think about the reverse should a key-value pair with a 0 sum be a placeholder?
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.
Makes sense to me. On this note, what do you think of adding a new section in the docs.
Stupid question: You mentioned nil keys
, but are we not talking about nil values
?
...
tree2.Update([]byte("key"), []byte(nil))
...
tree.Update([]byte("key"), []byte(nil), 5)
...
# Nil Values
A `Nil` value is treated as a `noop` as it utilizes the placeholder value in the SMT.
Assume `(key, value, weight)` pairs as follows:
* `(key, nil, 0)` -> DOES NOT modify the `root` hash -> noop
* `(key, nil, > 0)` -> DOES modify the `root` hash
* `(key, value, 0)` -> DOES modify the `root` hash
* `(key, value, > 0)` -> DOES modify the `root` hash
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.
Actually all of these will change the root from the default placeholder [32]byte
which may be confusing. I think this is because they are all actually creating a new leaf node thus changing the tree. However depending on the leaf's value its either the same as a placeholder leaf or not and thus doesn't count as being included in the tree.
@h5law Other than this one comment, which we just need to discuss and gree on, I'm ready to approve. #13 (comment) Is there anything else you want to do in this PR? |
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.
Left one last comment: #13 (comment)
Leaving the call to you if we sholdn't or shouldn't update the docs, but feel free to merge regardless
Reviewpad Report Fatal
|
Description
Summary generated by Reviewpad on 29 Jun 23 08:49 UTC
This pull request includes changes to multiple files in the repository. Here is a summary of the changes:
smt_testutil.go
file:smt_utils_test.go
.SMTWithStorage
struct to improve code organization and add comments.Update
method to improve error handling and include comments.Delete
method and added comments.ProveCompact
function.hasher.go
file:encoding/binary
package import.types.go
file:SparseMerkleSumTree
and methods for updating, deleting, getting, and computing the Merkle root and sum.SparseMerkleTree
interface'sProve
method to return a pointer to theSparseMerkleProof
struct.smt.go
file:smt_test.go
file to improve readability.VerifySumProof
andVerifyCompactSumProof
functions for sum tree proofs.README.md
file:proofs.go
file:smt_proofs_test.go
file:utils.go
file:tree.go
file:treeNode
interface.SMT
struct.licenses
file:bulk_test.go
file:Please review these changes and ensure they meet the requirements of the codebase.
Issue
Fixes #10
Type of change
Please mark the relevant option(s):
List of changes
Testing
go test ...
go test ...
go test -v
Required Checklist
godoc
format comments on touched members (see: tip.golang.org/doc/comment)If Applicable Checklist