-
Notifications
You must be signed in to change notification settings - Fork 217
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
Add a transcript protocol function that checks for identity points. #248
Conversation
This LGTM, but I know @oleganza had some comments about this approach so I don't want to merge it in just yet |
src/range_proof/mod.rs
Outdated
@@ -287,18 +287,19 @@ impl RangeProof { | |||
transcript.rangeproof_domain_sep(n as u64, m as u64); | |||
|
|||
for V in value_commitments.iter() { | |||
transcript.commit_point(b"V", V); | |||
transcript.validate_and_commit_point(b"V", V)?; |
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 completeness sake we need to allow zero V because the proof should be sound even with zero blinding factors, and with zero secret value.
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.
On a properly-generated Pedersen commitment, the blinding factor will be zero with negligible probability, so a zero blinding factor almost certainly indicates an RNG failure and I don't think there's a good reason to accept them.
It might be the case that some higher-level protocol uses inputs that aren't secret, as you mentioned (private communication), and so someone might choose a zero blinding factor. I'm not sure this is a good design compared to forming the commitment properly and giving the opening (v, v_blinding)
; if the blinding factor is set to zero, the committer still has to supply v
(since there's not an easy way to recover v
from vB
, even for low-entropy v
). So this "optimization" doesn't seem to really simplify the structure, the committer still has to supply the opening, it's just that the opening is smaller.
That said, I'm not totally set on forcing the V
commitments to be nonzero, I just don't see a good reason to allow it, and there are (in my opinion) good reasons not to allow it (see next 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.
I could see two options for resolving this:
- Remove the
V != 0
check to allow the zero-blinding-factors case, and leave other checks in place; - Leave all of the checks in place, and later, if
V != 0
turns out to block something, we can relax it in the future (since relaxing a check is easier to do later than adding one).
WDYT?
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.
Let's do (1) and merge this PR?
src/range_proof/mod.rs
Outdated
|
||
let y = transcript.challenge_scalar(b"y"); | ||
let z = transcript.challenge_scalar(b"z"); | ||
let zz = z * z; | ||
let minus_z = -z; | ||
|
||
transcript.commit_point(b"T_1", &self.T_1); | ||
transcript.commit_point(b"T_2", &self.T_2); | ||
transcript.validate_and_commit_point(b"T_1", &self.T_1)?; |
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.
T1 and T2 commit to “leftover” cross-terms and separated from the rest of the statement using non-zero challenge powers. There should not be a valid reason for them to not be allowed to be zero. If there is such reason, it must be specifically explored and called out. Maybe with some choice of prior challenges and zero blinding factors, some cross terms could actually end up being zeroes.
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 mean, maybe not in this RP protocol, but in R1CS, for instance)
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.
There should not be a valid reason for them to not be allowed to be zero. If there is such reason, it must be specifically explored and called out.
I disagree somewhat with this reasoning.
My reasoning for not allowing them to be zero is: allowing prover-supplied points to be the identity point is a risk, because it allows a prover to kill arbitrary terms in the verification equation (by setting those points to the identity, so that their coefficients disappear). It seems to be the case for Bulletproofs that this doesn't cause problems, but there are certainly other protocols where it does. Checking that the prover-supplied points aren't the identity closes off this line of attack upfront, even if, for this protocol, that line may not lead anywhere.
So I view this as a defense-in-depth mechanism. Legitimate proofs won't have zero terms (or will have them with negligible probability), so I don't think that this check costs anything to the protocol, but it does add a hedge against a class of risk to the protocol.
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.
As a follow-up, here's a concrete example of the kind of thing I'm worried about: https://twitter.com/claudiorlandi/status/1090705045333659648
The description of the protocol implicitly assumed that some data was not the identity and nobody noticed, leaving a gap. Preemptively checking that points are not the identity (unless there's a reason to allow them) seems to me like a low-cost, sensible precaution.
Relaxing the check does not always work compatibly in the scope of a larger system, e.g. in a blockchain protocol, where the set of invalid inputs cannot shrink w/o breaking consensus with older nodes. I'll try to think out loud about the available options: Option 1: implicit zero checks with explicit opt-outIf we have implicit check for !=0 for normal points, then we can have an explicit API for "opt out". For instance, we can consider a separate wrapper type like Pro This might be safer for all sorts of protocols that casually require a generator point, and need to ensure that such point is indeed a generator. Con Only one problem with this: for aforementioned blockchain applications, the user has to explicitly decide upfront which points (e.g. Non-issue Cross-term commitments are safe to be null, but can only be zero when the proof is completely degenerate (nothing is blinded at all), which is probably not an issue worth worrying about. Option 2: explicit zero-checks (opt-in)The point that must be a generator of a group (== "not identity") has a special type Pro Explicit strong subtype of all points. BulletproofsGens, PedersenGens can produce this type by default. Schnorr proof API takes that type making the requirement explicit. Code that does not care remains the same. Con Dangerously easy to write a protocol that does not require a Generator subtype. Since in most protocols generators are static, people do not have a habit to check for identity and treat all points as group generators by default. Option 3: explicit choiceTranscript has explicit choice of methods (naming TBD):
Pro The API forces the user to consider whether the point is supposed to be nullable or not, so either choice is not made lightly. Hopefully, avoiding any compatibility or safety issues down the road. The naming should be adjusted to make "nullable" sound scarier, and "nonnullable" more like a safer choice, but still being explicit. Con The transcript API is more awkward than we'd all like. Maybe can be improved with a variant from option 1. |
Hmm, how about option 4: use |
Yeah, this sounds like a nicer variant of option 3. How about you use |
Wait, for the rangeproof API it probably doesn't make sense to not validate V. For R1CS it does, though. |
I think a zero |
Updated this PR with the following changes:
|
No description provided.