-
Notifications
You must be signed in to change notification settings - Fork 69
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 SMT ExclusionProofs
#153
Conversation
@crodriguezvega @AdityaSripal This is still a WIP and the following must be done:
|
ExclusionProofs
ExclusionProofs
ExclusionProofs
ExclusionProofs
@crodriguezvega @AdityaSripal This PR is now ready for review. Go and rust implementations with test coverage are included. No JS support. This is partially due to me not seeing a usecase currently for JS and having no experience with TS. As it stands this logic will be used in our go project at Pocket and the rust will be used in my implementation of ICS-08 for our WASM client. |
@@ -1,5 +1,5 @@ | |||
DOCKER := $(shell which docker) | |||
HTTPS_GIT := https://github.com/cosmos/cosmos-sdk.git | |||
HTTPS_GIT := https://github.com/cosmos/ics23.git |
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 change was made as the current make proto-check-breaking
doesn't work it would say something about needing 2 contianers? I will revert this if someone can say how to make it work as intended.
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 a couple minor NITS.
Approving because core business logic LGTM but requires review/approval from an owner of the repo as well.
return ep | ||
} | ||
case *CommitmentProof_Batch: | ||
for _, sub := range p.Batch.Entries { |
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 the intended behaviour: for a batch of exclusion proofs we just return the first valid one?
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.
We are checking the batch for the exclusion proof with the correct key. If there are multiple then they are the same proof and we need only return 1.
When we validate a batch in entirety we go through all proofs and execute them individually. This is just that we were given a batch entry and are looking to prove just the one with the matching key.
@@ -43,7 +43,7 @@ var TendermintSpec = &ProofSpec{ | |||
}, | |||
} | |||
|
|||
// SmtSpec constrains the format for SMT proofs (as implemented by github.com/celestiaorg/smt) | |||
// SmtSpec constrains the format for SMT proofs (as implemented by github.com/pokt-network/smt) |
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 p.Leaf.PrehashKey != HashOp_NO_HASH { | ||
return nil, errors.New("exclusion proof must have leaf with PrehashKey == NO_HASH") | ||
} | ||
if p.Leaf.PrehashValue != HashOp_NO_HASH { | ||
return nil, errors.New("exclusion proof must have leaf with PrehashValue == NO_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.
Why is this a requirement? Consider adding a comment or updating the error message with the reasoning
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 a comment explaining this in the proto but will add again here
go/proof.go
Outdated
} | ||
// check if the actual value was a placeholder and replace with empty hash | ||
// assumes the placeholder value is [32]byte | ||
if bytes.Equal(p.ActualValueHash, make([]byte, 32)) { |
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.
Readability NIT: Move make([]byte, 32)
into a constant in this package or a local var and rename to smtPlaceholder
Thank you, @h5law! We have also contacted the Penumbra folks and ask them to take a look at the PR. Regarding JS support, we have talked in the past to actually stop support for it, so I wouldn't worry about it for now. If we end up still wanting to keep support, I could at some point port your Go implementation into TS. |
Would be great to connect with the Penumbra directly. In particular, I believe they might appreciate/adopt the work we're doing at https://github.com/pokt-network/smt |
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 don't understand the proof here. You're proving the existence of the actualPath and actualValueHash in the tree. But at what point does this prove that the key you provided does not exist?
There's nothing in the proof verification that is constraining the value of p.ActualPath
based on p.Key
Perhaps I'm just not understanding how an existence proof of the "unrelated key/value pair" as you say in the PR is a proof of exclusion for the key in question
So the actual path / value hash fields are populated by
|
@AdityaSripal Just wanted to follow up on what @h5law mentioned with a bit of a simplification and some diagrams (see [jmt]). We can prove exclusion of
|
I know there was a lengthy offline (slack/discord) discussion with @AdityaSripal @hdevalence and others related to not having @h5law could you capture and summarize the key takeaways and next steps? cc @musalbas for context |
The general sentiment is that instead of supporting newer proof mechanisms, the repo aims to support just a single form of As a result of this intention it was suggested to have the SMT library instead support the same "range based" non-membership proof as the JMT and IAVL tree. As a result I have opened this issue in the SMT library. I would like to add that although I will add support for this proof type I think that forcing newer tree types into using the same methods for generating proofs is not the way this library should be moving in. I feel that if we are able to support newer proof types, as long as the changes are backwards compatible we should do so. This enables the innovation to increase, potentially improvements in efficiency as time moves on. IBC is about interoperability not uniformity. |
Strongly agree with @h5law that only supporting a single proof method here is counter to the whole abstraction provided by ics23 |
@jackzampolin -- I agree. There's the whole question of dragons and the like re: ics23, will dive in for a bit. |
Thanks for all the comments here, everyone. Our apologies to @h5law for not providing public feedback on the PR earlier. The reason for that is that discussions happened privately on Slack approximately a month ago, and the understanding of the people involved in them was that Harry would try Penumbra's suggestion of adding support for range-based non-inclusion proofs in Pocket's SMT implementation in the same way that Penumbra did for their JMT implementation, instead of adding support for a new type of exclusion proof to ics23. Penumbra team's arguments were:
Even though Penumbra's and Harry's views on how to support non-inclusion proofs for SMT differed, we had the impression that Harry would still try to implement Penumbra's suggestion. Unfortunately that was a misunderstanding from our side, and the consequence was that this PR did not get enough attention since then. Last week @jackzampolin brought this PR again to our attention, and conversations with Harry followed. We agreed that we will pick this up again in approximately one week from now, once @AdityaSripal is back from holidays. Again, thanks everyone for the feedback and for putting this again in our radar. Whenever anybody notices that an issue of PR is falling through the cracks, feel free to ping us on Slack or Discord, or write a message on the relevant issue/PR. Due to our capacity constraints, we cannot treat everything with high priority, but with a bit of information and context, some rationale for prioritisation, and a pinch of kindness and understanding ❤️ we will do our best to make compromises to fit requests in as soon as possible. |
I understand that this is how you are constructing the proof. But I don't see where in the verification logic you are checking that this is what took place. My expectation would be that there are some checks that ensure that p.ActualPath is what you expect given the p.Key. Namely there should be some check that the path taken is a prefix of the desired key and that the path is not the key itself. I couldn't find any checks in the ICS23 code to that effect. Maybe I'm still fundamentally misunderstanding but this is why it took me some time to reply and asked Penumbra for their input since im still a bit confused by the PR. To illustrate my point I've written up this test case here: Here I took a valid existence proof of the key in question, and malformed it to create an exclusion proof for that same exact key that passes In fact as the verification exists right now, I'm pretty sure I could have taken a completely unrelated leaf and stuck it into the exclusion proof with any desired Key and had it pass. Again its possible I'm missing some very obvious point and maybe made some silly error in my test case writeup. But at the moment I don't see it. If it is the case that I'm right, then this PR needs to be reworked to add some check of the |
@h5law Did you have time to check out Aditya's comment above and the corresponding PR? |
@crodriguezvega Yes sorry I forgot to update this PR, @AdityaSripal and I synced offline on this. I would like to pick this issue back up and have it in full feature parity to the SMT doing the check itself at a later date. I still believe this is an important feature add to the The issue aditya pointed out is covered in the SMT itself but I looked over it here, although it took a long time Aditya's review will come in very helpful when I pick this up again in the near future. As a result I will be closing this PR and will open a new one when the time comes. |
This PR implements the support for SMT
ExclusionProofs
and verifies them by using converting them into anExistenceProof
and verifying either the existence of anil
value at the key provided or an unrelated key-value pair in place of the key provided.NOTE: In the
LeafOp
of theExclusionProof
the reason we set thePrehashKey
andPrehashValue
toHashOp_NO_HASH
is because theActualPath
andActualValueHash
fields should be populated by theNonMembershipLeafData
field of the SMT proof and as such should already be hashed in accordance with theTreeSpec
meaning hashing them again would result in an incorrect root computation.