-
Notifications
You must be signed in to change notification settings - Fork 35
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
Implement Verifiers for KZG and SNARK Proofs in Contracts #267
Conversation
…est script in the kzg_prover
… on Solidity verifier
…uction for generating verifier, commitment and proofs
I removed revert message in the |
contracts/src/GrandsumVerifier.sol
Outdated
// Memory positions for the verifying key. | ||
// The memory location starts at 0x200 due to the maximum operation on the ec_pairing function being 0x180, marking the maximum memory location used | ||
uint256 internal constant VK_MPTR = 0x200; | ||
uint256 internal constant VK_DIGEST_MPTR = 0x200; |
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.
VK_DIGEST_MPTR is not used
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, I will address this by copying only the values needed in the verifier from the VerifyingKey.
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.
Fixed at eb067b9
contracts/src/Summa.sol
Outdated
|
||
bytes memory slicedSnarkProof = new bytes(grandsumProof.length); | ||
for (uint256 i = 0; i < grandsumProof.length; i++) { | ||
slicedSnarkProof[i] = snarkProof[i + 64]; // Skip first 64 bytes, it's not for total balance. |
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.
Solidity now supports array slicing, maybe we can try to take advantage of that? https://docs.soliditylang.org/en/v0.6.0/types.html#array-slices
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.
Saved 146,361 gas by applying the array slice to the submitCommitment
method. Thanks!
It's updated at eb067b9
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.
Wow, I didn't even expect such an improvement, sounds great!
contracts/src/Summa.sol
Outdated
|
||
require(grandSumVerifier.verifyProof(verifyingKey, combinedProofs, totalBalances), "Invalid grandsum proof"); | ||
|
||
// Slice the proof aa length as grandsumProof |
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 comment seems to be unrelated to the code
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.
It's removed at 0230050
contracts/src/Summa.sol
Outdated
// Slice the proof aa length as grandsumProof | ||
commitments[timestamp] = slicedSnarkProof; | ||
|
||
emit LiabilitiesCommitmentSubmitted(timestamp, totalBalances, slicedSnarkProof); |
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 that we can actually put the combined proof into the event as it binds together the range check and the grand sum opening proofs, and also store the combined proof in the commitments mapping.
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 agree with including both the snark proof and the grand sum proof in the event. However, I'm unsure about storing the grand sum proof in the commitment mapping. Is there a potential use for it in the future?
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.
Agreed, no need for the grand sum proof in the commitments mapping :)
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.
It's updated at 6db5fb7
contracts/src/Summa.sol
Outdated
uint256[] memory challenges, | ||
uint256[] memory values | ||
) public view returns (bool) { | ||
require(values.length > 1, "Invalid values length"); |
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 can check the exact values length here because we know the cryptocurrencyNames
length that was passed in the constructor.
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.
Ah yes, It been fixed at 0230050
contracts/test/Summa.ts
Outdated
}); | ||
|
||
it("should not submit an invalid commitment", async () => { | ||
it("should reject submit an invalid total balances", async () => { |
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'd say either "reject" or "not submit"
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.
It's updated at 6db5fb7
contracts/test/Summa.ts
Outdated
}); | ||
|
||
it("should revert if the caller is not the owner", async () => { | ||
it("should reject submit when grandsum proof length mismatches with total balances", async () => { |
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.
Same here with reject/submit
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.
It's updated at 6db5fb7
contracts/test/Verifiers.ts
Outdated
expect(await snarkVerifier.verifyProof(verifyingKey.address, commitmentCalldata.range_check_snark_proof, [1])).to.be.true; | ||
}); | ||
|
||
it("should fail to verify snark proof without the number of instances", async () => { |
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 this test is not necessary because the instance issue should be fixed by merging the upstream changes.
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.
Okay, I will remove it.
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.
Replaced another test case instead of this at 6db5fb7
contracts/test/Verifiers.ts
Outdated
commitmentCalldata = deploymentInfo.commitmentCalldata; | ||
|
||
// InclusionVerifier requires BN256G2 contract for performing elliptic curve operations on G2 subgroup | ||
// const bn256g2 = await deployBN256G2(); |
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.
BN256G2 mention can be removed
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.
It removed at 6db5fb7
let mut grand_sums_kzg_proof = Vec::new(); | ||
for balance_column in 1..(N_CURRENCIES + 1) { | ||
let f_poly = advice_polys.advice_polys.get(balance_column).unwrap(); | ||
let kzg_commitment = commit_kzg(¶ms, f_poly); |
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 can be replaced with the committed point taken from the zk-proof transcript.
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.
Yes, Indeed! Thanks for point out!
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 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.
Great tip! It was much helped
It updated at 6db5fb7
let mut inclusion_proof: Vec<Vec<u8>> = Vec::new(); | ||
for column_index in column_range { | ||
let f_poly = advice_polys.advice_polys.get(column_index).unwrap(); | ||
let kzg_commitment = commit_kzg(¶ms, f_poly); |
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.
Same here, the commitment can be taken from the zk-proof transcript.
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.
It updated at 6db5fb7
struct InclusionProofCallData { | ||
proof: String, | ||
challenges: Vec<U256>, | ||
username: String, |
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 rename "username" to "userId" because it's not a plain-text username but is supposed to be a 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.
Yes, that makes sense. Okay, I will replace 'username' with 'userId'
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.
It updated at 6db5fb7
kzg_prover/bin/gen_verifier.rs
Outdated
@@ -73,6 +72,10 @@ fn main() { | |||
); | |||
assert!(result.is_ok()); | |||
|
|||
let result_unwrapped = result.unwrap(); | |||
result_unwrapped.0.expect("prover should not fail"); | |||
let _advice_polys = result_unwrapped.1.clone(); |
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.
_advice_polys is not used
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.
It removed at 6db5fb7
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.
Awesome job! Let's follow the consistent naming pattern for grand sum-related things (separate "grand sum" in text and proper snake/camel case in code, e.g., "grand_sum" and "grandSum", including the file names).
Thanks, That's great naming idea |
it("should fail to verify snark proof without the number of instances", async () => { | ||
await expect(snarkVerifier.verifyProof(verifyingKey.address, commitmentCalldata.range_check_snark_proof, [])).to.be.reverted; | ||
it("should revert grand sum proof", async () => { | ||
await expect(snarkVerifier.verifyProof(verifyingKey.address, commitmentCalldata.grand_sums_batch_proof, [1])).to.be.reverted; |
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 should it revert here?
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.
Because the verifier is for verifying snark proof, not for verifying grand sum proof.
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 would rename the test to something like "should revert with invalid proof".
inclusionProof = inclusionCalldata.proof; | ||
userId = inclusionCalldata.user_id; | ||
challenges = inclusionCalldata.challenges; | ||
userIdBigUint = inclusionCalldata.user_values[0]; |
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.
Do we still need the userId
if we have it in inclusionCalldata.user_values[0]
?
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.
Actually 'userId' is not used anywhere in the test code. I will remove it on the test code.
Would it be better to remove it from the csv file as well?
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 think we can remove it from the csv, it is used in some tests (e.g., test_valid_univariate_grand_sum_full_prover
) and should be used in production as well.
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! Can merge after resolving the conflicts.
a48ea0b
to
6e52b9d
Compare
contracts/test/Verifiers.ts
.kzg_prover/bin
as a JSON file.gen_commitment.rs
andgen_inclusion_proof.rs
.gen_verifier.rs
script inkzg_prover
.ProverGWC
for further benchmarks on a higher number of currencies.Todo