-
Notifications
You must be signed in to change notification settings - Fork 53
adds support for raw key instead of hashed key #64
base: master
Are you sure you want to change the base?
Conversation
@adlerjohn Please take a look and let me know if this is what is needed so I continue fixing the other tests etc. |
Codecov Report
@@ Coverage Diff @@
## master #64 +/- ##
==========================================
+ Coverage 85.62% 89.16% +3.54%
==========================================
Files 6 6
Lines 466 480 +14
==========================================
+ Hits 399 428 +29
+ Misses 39 26 -13
+ Partials 28 26 -2
Continue to review full report at Codecov.
|
adds key size to map store + adds tests for it
Questions:
|
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.
I left some comments in the code.
In general, I think that default behavior of the library should be preserved (enable users to use arbitrary keys), and raw keys support should be actually added (instead of replacing current way of operation).
This can be added as an Option
, that changes the behavior of treeHasher.path
method to no-op.
_, ok := sm.m[string(key)] | ||
if ok { | ||
delete(sm.m, string(key)) | ||
return nil | ||
} | ||
return &InvalidKeyError{Key: key} | ||
} | ||
|
||
func (sm *SimpleMap) checkKeySize(key []byte) error { |
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.
For SparseMerkleTree.values
this function implies that all keys in SMT must have the same length. This is fine if user is going to hash keys before adding to SMT, but in more general case it's a very strong limitation.
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.
I think the SMT is by construction assumed to be perfect. Allowing different key sizes...doesn't really make sense? How would that even work?
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.
I thought it should only support a fixed size of keys, no ?
The checkKeySize
is not exported (If I am not wrong), it is only used internaly. What it does is verify the length of the provided key if it matches the key size or return an error otherwise. I put it in a function to avoid rewriting the same code over and over again.
Do you mean we can have any key length ? I guess that wasn't the case even before this PR, since it was using a specific hashing algorithm to hash the keys and the depth of the tree was gotten via hasher.size()
...
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.
I totally agree, that SMT require fixed key size internally. My only concern is that, previously our SMT public interface was a black-box/high-level/general-purpose-container type of thing (see README.md with _, _ = tree.Update([]byte("foo"), []byte("bar"))
). This change is a complete pivot, where de-facto part of implementation is exposed to the user, and user has to be aware of this.
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.
true, it is a breaking change. However, it will impact the interface only at the time of creation of the map stores and verification of proofs.
For addBranch
, it was a mistake from my side to put the keySize
as a parameter since it should be checked against the dsmst
's map store and not against the one passed in params (will make the change shortly).
Previously, I think when verifying a proof, we were passing a hasher
, from which we extracted the keySize
. So, we were verifying a proof against a certain hasher
and a keySize
. Except that the latter wasn't exposed since it was extracted from the hasher. Now that the key size doesn't relate to the hasher, it's alright to pass it as parameter.
What do you think ?
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.
The actual function signatures of Get
, Set
, Update
, Delete
, etc are not changed, but there is an extra "contract" added (fixed length keys). While updating SMT dependency, user has to potentially update all invocations of those methods.
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.
Aaah, got you now 👍 makes sense
Thanks for the comments, will address them tomorrow. |
smt.go
Outdated
// This is a non-membership proof that involves showing a different leaf. | ||
// Add the leaf data to the proof. | ||
nonMembershipLeafData = leafData | ||
} | ||
} | ||
|
||
proof := SparseMerkleProof{ | ||
return SparseMerkleProof{ |
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.
Is this change idiomatic Go? I prefer the old version personally since it's clearer what's being returned without having to parse two concepts at once. The compiler will optimize away the variable anyways, if performance was the concern.
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.
I got this and similar ones flagged by a linter... Apparently, I am using a more exhaustive linter, maybe we should agree on a linter config for all the repos, and respect all the errors it is showing.
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.
Hm. How about revert these changes for now, then we can open a separate issue (potentially also to be implemented across the org) on linting?
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.
sounds good. Should I create an issue ? or just leave it for now ?
Just for clarification: I totally agree, that raw keys can be very useful, I understand the logic behind this change. But IMHO it's a low hanging fruit, to be able to use SMT with both raw (advanced use, turned on by option) and hashed keys (by default). |
…apStore` instead
@tzdybal sounds good to have both, yes. I can start digging into it as soon as I get the green light 👍 |
Having the option for both modes isn't bad IMO. Having the option for raw keys is a must, beyond that extra features are gravy on top. |
@adlerjohn should I get going with the implementation ? in // with the explorer stuff ? Also, what do you think about these ?
|
Stopping work on this for now. Will pick it up later. |
Fixes #40.
It adds a
keySize
field to all SMT related structs and uses it to access values insmt.values
map.Update:
The
keySize
is now part of theMapStore
and it is being passed around as parameter wherever needed.