Skip to content
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!: remove verifier RNG requirement #116

Merged

Conversation

AaronFeickert
Copy link
Contributor

@AaronFeickert AaronFeickert commented Feb 13, 2024

The verifier currently requires support for a random number generator, either provided by the caller or taken from OsRng. This is only to produce weights used in the batch verification process; the weights do not need to be cryptographically secure, but must not be known to the prover. This is fine if the verifier has access to a good random number generator, but is not ideal or particularly flexible; in particular, it likely precludes having a WASM verifier.

This PR uses TranscriptRng functionality to produce these weights deterministically. It removes the need for the verifier to supply or support any random number generator.

We start by instantiating a new Merlin weight transcript whose only purpose is to bind all proofs together. After processing each proof's RangeProofTranscript to produce challenges, we include the prover's responses in the transcript and then use the corresponding TranscriptRng to fetch a pseudorandom u64 that goes into the weight transcript. Once all proofs have been bound in this way, we use the weight transcript's TranscriptRng to generate the weights.

Note that because we still use TranscriptRng functionality, we need to include a random number generator to satisfy the API. To do this, we build a fake NullRng that only outputs zero. This is not safe in general, but is fine in this case.

It's important that we include the prover's responses in each transcript. Normally we don't ever need to do this; however, we don't want the prover to be able to manipulate them in an attempt to bias the weight transcript. If we were doing individual verification or random weighting, this would not be problematic. However, we want to guard against a prover who may be able to influence the batch structure used by the verifier. This is defense in depth and costs effectively nothing.

This is technically a breaking change, since it removes verify_batch_with_rng from the public API; the existing verify_batch should be used instead, and no longer requires the rand feature.

Closes #110.

BREAKING CHANGE: Removes verify_batch_with_rng from the public API. No longer requires that verify_batch have the rand feature enabled.

Copy link
Contributor

@hansieodendaal hansieodendaal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the verifier should pass in a standard rng, then inside verify_batch_with_rng we use that to seed a crypto rng. The only interface change would be pub fn verify_batch_with_rng<R: CryptoRngCore> to pub fn verify_batch_with_rng<R: RngCore>.

@AaronFeickert
Copy link
Contributor Author

This would still limit the effective entropy to that of the RngCore input, and I'm not sure what you gain from it. There already exist seedable CryptoRngCore generators that don't use OS-supplied entropy, but these are similarly limited by the seed quality. The underlying problem is that some targets can't use OS-supplied randomness at all, which implies that they couldn't properly seed any generator.

The idea here is to remove the question of generator quality and availability entirely, and have the verifier handle it using the transcripts instead.

Copy link
Contributor

@hansieodendaal hansieodendaal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

Looking at it again, I like using the null rng in there, as it conveys a specific message about the verifier's requirement, and is also reflected in the API.

@AaronFeickert
Copy link
Contributor Author

AaronFeickert commented Feb 20, 2024

It's probably worth noting that we could get the same effect by simply generating a cryptographic hash of all proofs, and then using it to seed a random number generator to get the verifier weights. Indeed, this would likely be faster when using a hasher like those of the Blake2 family (my initial and incomplete tests suggest maybe on the order of a microsecond, if that).

However, I don't think this is an optimal idea:

  • It effectively duplicates computation that's already done using the existing verifier transcript reconstruction.
  • It requires that the proof hashing be done correctly and safely, which is much easier to do with Merlin.
  • It requires a proper choice of seeded random number generator.

Overall, I think the Merlin-based approach in this PR is safer, more idiomatic, and worth any trivial efficiency hit.

@hansieodendaal hansieodendaal merged commit 8759a59 into tari-project:main Mar 4, 2024
8 of 9 checks passed
@AaronFeickert AaronFeickert deleted the verifier-transcript-rng branch March 4, 2024 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Verifier requires a random number generator
3 participants