-
Notifications
You must be signed in to change notification settings - Fork 771
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
trie: Better error checking for invalid proofs #1373
Conversation
Codecov Report
Flags with carried forward coverage won't be shown. Click here to find out more. |
@ryanio I'm not sure if I'm handling this exactly right or not but the way that the documentation for |
thanks for taking this on! it looks like the library was designed to return null for these keys, check out these tests which are now failing with the new error (line 26): ethereumjs-monorepo/packages/trie/test/proof.spec.ts Lines 22 to 46 in 7a2301c
the very last equals is interesting, you would think as least a completely invalid proof would throw as that what the typedoc you linked to states, but that's also checked for null (line 45 above) it is a bit perplexing, i'll see if I can get any thoughts or history/context from @s1na :) |
This would be a valid exclusion proof, i.e. a proof that a leaf in the tree is empty which has its own use-cases. I understand how it'd be useful to distinguish between a valid exclusion proof and an invalid proof and returning |
Now that I've soaked in this a little more, I think I'm starting to understand the logic a little better but I'm sure I'm still missing things. Is this an accurate description of how
Here's where I'm just not that deep on merkle proofs/tries but should you be able to construct a trie from any random set of bytes? If so, what constitutes an invalid proof? If we never generate a natural exception when constructing the trie from a proof, doesn't that mean that a prooftrie that doesn't contain the provided key just show evidence of non-existence of that key within the trie and nothing more? What defines it as an invalid proof? |
I think that
An invalid proof for a key would be a set of nodes which you can't traverse with the key or a prefix of the key reaching to a termination (because there are missing nodes). In this case I think the This is the behaviour that is implemented in go-ethereum: https://github.com/ethereum/go-ethereum/blob/a1f16bc74c7efb593db2982c92222d1e4a201c25/trie/proof.go#L103 |
thanks all for the discussion, here is the old (pre-refactored) verifyProof which does seem to have additional checks and errors |
@ryanio That looks like a straight port of geth's code if I'm reading it correctly. Maybe the best course of action is just to bring that back in? |
Thanks @ryanio for digging up the older version. That's essentially the usual algorithm for verifying a proof, i.e.:
Now this implemented version does this in a hacky way. It inserts all the proof nodes in the database, and then tries to
It might be possible to distinguish between invalid and valid exclusion proofs via a minor tweak where |
Thanks @s1na. I think I have an idea how to resolve leveraging your current implementation. I think if we insert a |
that seems like it might also help solve #1055 (comment) |
At the end of the day, if we're going to continue to use the existing logic and not revert back to what @s1na noted as the conventional way for identifying an invalid proof, we have to put some thought into onFound that's buried inside the The way I'm reading the code, a valid exclusion proof would result in a final state where the |
The use case for validating a proof, is when someone else sends you the proof, and you do not trust them. This software is meant to be run locally, to verify a key-value pair without trusting the source. This software does not have any method of creating an invalid proof, maybe such a function would be useful for understanding the tests. I wrote the tests above, and I agree they are very unclear, because I found that making an invalid proof (and testing many different cases) was somewhat difficult to do. First I will say that I think the best/easiest solution might be to just implement the fix I described here. Now let me try to describe how inserting the proof nodes into a tree and then Hope this helps |
I think I follow your logic but I still have two challenges with it:
I don't have a strong opinion one way or the other on this and I'm not an expert on merkle proofs (as demonstrated above) so just looking to make sure we account for this situation correctly. |
I opened the issue that may have landed this PR #1368 We need to verify an Ethereum Storage Proof submitted by a user, and the reason we picked the library is because the
Why should |
@brickpop that was the existing behavior in mpt v2.3.2, there was some refactoring that happened in v3+ that seems to have introduced this which we are trying to fix with this PR. There seems to be two routes we can go here: one is to revert back to the v2.3.2 logic which matches geth's implementation, or resolve with the current design. |
ok I'm working on this a bit late at night but I think I got the gist and introduced a new |
@ryanio Anything outstanding on this one? I'm waiting on the tests to re-run from merging in master but seems like this one might be ready to go or is it considered a breaking change since we added that new optional parameter to the |
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.
@acolytec3 thanks, LGTM, really love the readme updates for explaining proof of non-existence.
I don't believe it's breaking because it's an optional parameter that defaults to the prior behavior. It is still a little strange to me to add to the Trie.get
param though, but it was the only way I could think of. I would be open to other ideas.
I wonder if we should consider a bug fix release with this if invalid proofs are indeed totally broken?
Let's also wait for an approval or any thoughts from Holger before merging in. |
Might take me some more days until I worked through this here and can do some qualified comment. |
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.
Looks good, left a few minor comments
Co-authored-by: Gabriel Rocheleau <contact@rockwaterweb.com>
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.
LGTM, nice work, thanks everyone for this extensive and clarifying discussion!
Will merge and relatively soon prepare a bugfix release on this.
Changes from this PR have been published along |
Fixes #1368.
Adds a new check to the
baseTrie.verifyProof
function to verify that the proof trie for the provided key actually contains the value associated with that key and throws if the key doesn't exist in the trie (as described in the function's behavior).