diff --git a/examples/CRISP/circuits/src/ecdsa.nr b/examples/CRISP/circuits/src/ecdsa.nr index 1ef2a4ae01..91fba9ae0a 100644 --- a/examples/CRISP/circuits/src/ecdsa.nr +++ b/examples/CRISP/circuits/src/ecdsa.nr @@ -6,10 +6,11 @@ use keccak256::keccak256; -/// Verifies an ECDSA signature over a hashed message. +/// Validates an ECDSA signature over a hashed message. /// -/// This function verifies that a signature was created by the holder of the private key +/// This function validates that a signature was created by the holder of the private key /// corresponding to the provided public key, and that it signs the given hashed message. +/// The function asserts internally, ensuring the signature is valid. /// /// # Arguments /// * `hashed_message` - The Keccak256 hash of the message being signed (32 bytes) @@ -17,19 +18,18 @@ use keccak256::keccak256; /// * `pub_key_y` - The y-coordinate of the public key (32 bytes, big-endian) /// * `signature` - The ECDSA signature (64 bytes: r || s, both 32 bytes big-endian) /// -/// # Returns -/// `true` if the signature is valid, `false` otherwise. -/// /// # Note /// The signature is verified using secp256k1 curve (same as Ethereum). The message /// should already be hashed before calling this function. -pub fn verify_signature( +pub fn validate_signature( hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64], -) -> bool { - std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) +) { + let is_valid = + std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(is_valid == true); } /// Derives an Ethereum address from a secp256k1 public key. @@ -105,7 +105,7 @@ fn test_derive_address() { } #[test] -fn test_verify_signature() { +fn test_validate_signature() { let hashed_message = [ 67, 126, 157, 164, 162, 165, 56, 242, 155, 214, 113, 196, 83, 198, 228, 36, 174, 104, 152, 87, 167, 108, 64, 34, 234, 161, 122, 55, 44, 62, 151, 55, @@ -124,11 +124,11 @@ fn test_verify_signature() { 124, 118, 143, 228, 126, 216, 173, 160, 231, 62, 52, 188, 154, 110, 230, 183, 71, 36, 161, 171, 163, 213, 62, 223, 152, ]; - assert(verify_signature(hashed_message, pub_key_x, pub_key_y, signature) == true); + validate_signature(hashed_message, pub_key_x, pub_key_y, signature); } #[test] -fn test_verify_signature_sdk_input() { +fn test_validate_signature_sdk_input() { let hashed_message = [ 200, 232, 98, 162, 80, 131, 242, 57, 252, 76, 226, 45, 127, 206, 207, 39, 206, 44, 211, 171, 113, 67, 121, 68, 78, 253, 202, 79, 29, 128, 130, 76, @@ -149,11 +149,14 @@ fn test_verify_signature_sdk_input() { 236, 18, ]; - assert(verify_signature(hashed_message, pub_key_x, pub_key_y, signature) == true); + validate_signature(hashed_message, pub_key_x, pub_key_y, signature); } -#[test] -fn test_fail_verify_signature() { +#[test(should_fail)] +fn test_fail_validate_signature() { + // This test verifies that invalid signatures cause validation to fail. + // The test itself will fail (assertion failure) when validate_signature is called + // with an invalid signature, which demonstrates that invalid signatures are properly rejected. let hashed_message = [ 67, 126, 157, 164, 162, 165, 56, 242, 155, 214, 113, 196, 83, 198, 228, 36, 174, 104, 152, 87, 167, 108, 64, 34, 234, 161, 122, 55, 44, 62, 151, 55, @@ -173,7 +176,8 @@ fn test_fail_verify_signature() { 171, 163, 213, 62, 223, 151, ]; - assert(verify_signature(hashed_message, pub_key_x, pub_key_y, signature) == false); + // This call should fail (assertion failure) because the signature is invalid + validate_signature(hashed_message, pub_key_x, pub_key_y, signature); } #[test] diff --git a/examples/CRISP/circuits/src/main.nr b/examples/CRISP/circuits/src/main.nr index 05c40689e0..56ac71f7b8 100644 --- a/examples/CRISP/circuits/src/main.nr +++ b/examples/CRISP/circuits/src/main.nr @@ -17,7 +17,7 @@ mod constants; mod ciphertext_addition; use ciphertext_addition::CiphertextAddition; mod ecdsa; -use ecdsa::{address_to_field, derive_address, verify_signature}; +use ecdsa::{address_to_field, derive_address, validate_signature}; mod merkle_tree; use merkle_tree::get_merkle_root; mod utils; @@ -43,11 +43,11 @@ use utils::{check_coefficient_values_with_balance, check_coefficient_zero}; /// impossible for a voter to prove which ciphertext was their actual vote, preventing them from /// providing a verifiable receipt to a coercer or briber. /// -/// The circuit verifies all inputs and returns the appropriate ciphertext. -/// Specifically, it returns a tuple of ciphertext components depending on the case: -/// - **Actual vote**: `(ct0is, ct1is)` - the new vote ciphertext -/// - **Mask vote (first vote)**: `(ct0is, ct1is)` - zero ciphertext -/// - **Mask vote (updating slot)**: `(sum_ct0is, sum_ct1is)` - sum of previous votes in slot +/// The circuit verifies all inputs and returns the appropriate ciphertext commitment. +/// Specifically, it returns a Field commitment depending on the case: +/// - **Actual vote**: `ct_commitment` - commitment to the new vote ciphertext +/// - **Mask vote (first vote)**: `ct_commitment` - commitment to the zero ciphertext +/// - **Mask vote (updating slot)**: `sum_ct_commitment` - commitment to the sum of previous votes in slot /// fn main( // Ciphertext Addition Section @@ -88,23 +88,10 @@ fn main( slot_address: pub Field, balance: Field, is_first_vote: pub bool, + is_mask_vote: bool, ) -> pub Field { // ============================================================================ - // STEP 1: Authentication - Derive voter's address from signature - // ============================================================================ - // Verify that a constant message was signed by the holder of the private key - // corresponding to the provided public key. Then the address is derived from - // that public key and compared later to the slot address if the vote is an actual - // vote. - // - // For ACTUAL VOTES: Signature must be valid (voter authenticates themselves) - // For MASK VOTES: Signature may be invalid (anyone can submit mask votes) - let is_signature_valid = - verify_signature(hashed_message, public_key_x, public_key_y, signature); - let address = address_to_field(derive_address(public_key_x, public_key_y)); - - // ============================================================================ - // STEP 2: Eligibility - Merkle Tree Proof + // STEP 1: Eligibility - Merkle Tree Proof // ============================================================================ // Verify that the (slot_address, balance) pair exists in the eligibility // Merkle tree. The proof demonstrates membership without revealing the entire tree. @@ -126,10 +113,10 @@ fn main( assert(merkle_root_calculated == merkle_root); // ============================================================================ - // STEP 3: BFV Encryption Verification (GRECO) + // STEP 2: BFV Encryption Verification (GRECO) // ============================================================================ // Verify that the ciphertext (ct0is, ct1is) is a valid encryption of the - // plaintext k1 under the public key (pk0is, pk1is). This enusres the ciphertext + // plaintext k1 under the public key (pk0is, pk1is). This ensures the ciphertext // is correctly formed. // // This check applies to BOTH cases: @@ -157,78 +144,70 @@ fn main( assert(greco.verify()); // ============================================================================ - // STEP 4: Ciphertext Addition Verification + // STEP 3: Vote Type Detection and Return Logic // ============================================================================ - // Verify that the sum ciphertext correctly represents the homomorphic addition - // of a zero vote to the previous ciphertext without decrypting. This is only checked - // for mask votes, and only when the slot is not empty. - // - // Mask votes add zero to the previous ciphertext, creating a different ciphertext - // with the same plaintext as the previous ciphertext. - // - // Commitments are cryptographic hashes of the polynomial coefficients that bind the - // prover to specific ciphertext values. Three commitments are generated: - // - prev_ct_commitment: commitment to the previous ciphertext (prev_ct0is, prev_ct1is) - // - ct_commitment: commitment to the new vote ciphertext (ct0is, ct1is) - // - sum_ct_commitment: commitment to the sum ciphertext (sum_ct0is, sum_ct1is) + // The circuit branches into two cases based on the is_mask_vote flag: // - // The prev_ct_commitment is verified against the actual polynomials to ensure the - // prover hasn't tampered with the previous ciphertext. This check is only performed - // for mask votes when it's not the first vote (i.e., when there's a previous ciphertext - // to verify). The commitments are then used in the Fiat-Shamir transform to generate - // random challenges for the Schwartz-Zippel lemma verification, ensuring the addition - // equations hold without revealing the full polynomial coefficients. - let _prev_ct_commitment = generate_commitment::(prev_ct0is, prev_ct1is); - let ct_commitment = generate_commitment::(ct0is, ct1is); - let sum_ct_commitment = generate_commitment::(sum_ct0is, sum_ct1is); - - let ct_add: CiphertextAddition = CiphertextAddition::new( - GRECO_CONFIGS, - ct0is, - ct1is, - ct_commitment, - prev_ct0is, - prev_ct1is, - _prev_ct_commitment, - sum_ct0is, - sum_ct1is, - sum_ct_commitment, - sum_r0is, - sum_r1is, - ); - - let is_ct_add_valid = ct_add.verify(); - - // ============================================================================ - // STEP 5: Vote Type Detection and Return Logic - // ============================================================================ - // The circuit branches into two cases based on signature validity and address match: - // - // CASE 1: ACTUAL VOTE - // Condition: Signature valid AND address matches slot + // CASE 1: ACTUAL VOTE (is_mask_vote == false) // - This is an eligible voter casting a vote // - Verify vote amount <= balance - // - Return new vote ciphertext (ct0is, ct1is) + // - Validate signature over the hashed message (voter authenticates themselves) + // - Verify address matches slot address + // - Return new vote ciphertext commitment (ct_commitment) // - // CASE 2: MASK VOTE - // Condition: Signature invalid OR address mismatch + // CASE 2: MASK VOTE (is_mask_vote == true) // - This is anyone submitting a zero vote to mask slot activity - // - Verify vote is actually zero (k1 must be zero) - // - If first vote in slot: return zero ciphertext (ct0is, ct1is) - // - If updating slot: verify addition and return sum of previous votes - if (is_signature_valid == true) & (slot_address == address) { + // - Verify vote is zero (k1 must be zero) + // - If first vote in slot: return zero ciphertext commitment (ct_commitment) + // - If updating slot: + // * Verify that the sum ciphertext correctly represents the homomorphic addition + // of a zero vote to the previous ciphertext without decrypting + // * Mask votes add zero to the previous ciphertext, creating a different ciphertext + // with the same plaintext as the previous ciphertext + // * Generate commitments for prev_ct and sum_ct (ct_commitment is generated before) + // * Verify prev_ct_commitment matches the actual polynomials to ensure the prover + // hasn't tampered with the previous ciphertext + // * Verify ciphertext addition using commitments and Fiat-Shamir transform with + // Schwartz-Zippel lemma verification + // * Return sum ciphertext commitment (sum_ct_commitment) + + // Generate the vote ciphertext commitment. + let ct_commitment = generate_commitment::<512, 2, 36>(ct0is, ct1is); + + if is_mask_vote == false { check_coefficient_values_with_balance(k1, Q_MOD_T_MOD_P, balance); + validate_signature(hashed_message, public_key_x, public_key_y, signature); + + let voter_address = address_to_field(derive_address(public_key_x, public_key_y)); + assert(slot_address == voter_address); ct_commitment } else { - let is_vote_zero = check_coefficient_zero(k1); - assert(is_vote_zero == true); + check_coefficient_zero(k1); if is_first_vote { ct_commitment } else { + let _prev_ct_commitment = generate_commitment::<512, 2, 36>(prev_ct0is, prev_ct1is); + let sum_ct_commitment = generate_commitment::<512, 2, 36>(sum_ct0is, sum_ct1is); + + let ct_add: CiphertextAddition<512, 2, 36, 36, 36> = CiphertextAddition::new( + GRECO_CONFIGS, + ct0is, + ct1is, + ct_commitment, + prev_ct0is, + prev_ct1is, + _prev_ct_commitment, + sum_ct0is, + sum_ct1is, + sum_ct_commitment, + sum_r0is, + sum_r1is, + ); + assert(prev_ct_commitment == _prev_ct_commitment); - assert(is_ct_add_valid); + assert(ct_add.verify()); sum_ct_commitment } diff --git a/examples/CRISP/circuits/src/utils.nr b/examples/CRISP/circuits/src/utils.nr index 10b17c4ce3..27473b2c7f 100644 --- a/examples/CRISP/circuits/src/utils.nr +++ b/examples/CRISP/circuits/src/utils.nr @@ -93,13 +93,10 @@ pub fn check_coefficient_values_with_balance( /// # Arguments /// * `k1` - The plaintext polynomial encoding the vote /// -/// # Returns -/// `true` if all vote coefficients are zero, `false` otherwise. -/// /// # Vote Regions Checked /// - NO votes: coefficients [0, HALF_LARGEST_MINIMUM_DEGREE) /// - YES votes: coefficients [HALF_D, HALF_D + HALF_LARGEST_MINIMUM_DEGREE) -pub fn check_coefficient_zero(k1: Polynomial) -> bool { +pub fn check_coefficient_zero(k1: Polynomial) { let HALF_D = D / 2; // Define vote region boundaries @@ -109,24 +106,15 @@ pub fn check_coefficient_zero(k1: Polynomial) -> bool { let START_INDEX_N = 0; let END_INDEX_N = HALF_LARGEST_MINIMUM_DEGREE; - let mut res = true; - // Check YES vote region: all coefficients must be zero for i in START_INDEX_Y..END_INDEX_Y { - if k1.coefficients[i] != 0 { - res = false; - } + assert(k1.coefficients[i] == 0); } // Check NO vote region: all coefficients must be zero for i in START_INDEX_N..END_INDEX_N { - if k1.coefficients[i] != 0 { - res = false; - } + assert(k1.coefficients[i] == 0); } - - // Return true only if both regions are completely zero - res } #[test] @@ -205,7 +193,7 @@ fn test_check_coefficient_values_fail() { check_coefficient_values_with_balance(pol, 1, 100); } -#[test] +#[test(should_fail)] fn test_check_coefficient_zero_fail() { let pol = Polynomial { coefficients: [ @@ -217,7 +205,7 @@ fn test_check_coefficient_zero_fail() { ], }; - assert(check_coefficient_zero(pol) == false); + check_coefficient_zero(pol); } #[test] @@ -231,5 +219,5 @@ fn test_check_coefficient_zero() { ], }; - assert(check_coefficient_zero(pol) == true); + check_coefficient_zero(pol); } diff --git a/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol b/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol index e98174c288..1ed10e7a17 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol @@ -5,87 +5,87 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity >=0.8.21; -uint256 constant N = 262144; -uint256 constant LOG_N = 18; +uint256 constant N = 524288; +uint256 constant LOG_N = 19; uint256 constant NUMBER_OF_PUBLIC_INPUTS = 22; -uint256 constant VK_HASH = 0x1b70cd4645c6848a427928287d3a522940046ad3a0a07830d9ed5402ad0687f5; +uint256 constant VK_HASH = 0x17d6bf392f96d9d4c2616045ca7298f94a7811f71e89e21e811df6ea8fda2d71; library HonkVerificationKey { function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { Honk.VerificationKey memory vk = Honk.VerificationKey({ - circuitSize: uint256(262144), - logCircuitSize: uint256(18), + circuitSize: uint256(524288), + logCircuitSize: uint256(19), publicInputsSize: uint256(22), ql: Honk.G1Point({ - x: uint256(0x14a0a19af87c2b7df627250d1ac6c5d55d75a58778f8e29595157428ac287a34), - y: uint256(0x287a5a5edc8f75bef06b3d796c2fc1654d9eea0a329fdfcfb8a19e32250daf5d) + x: uint256(0x201ca76d778ca0640a230dff71a7345c30a05b33f94202574ac13241a43ec601), + y: uint256(0x2f63fc1bd520fc36e2059a0bf4c9adcd8393b0887da0c1741a7fe7397e9c7da8) }), qr: Honk.G1Point({ - x: uint256(0x2cf44e06d8100798cfc546de969e62bcf6c63a3fe6377d3aa284d9d251e72087), - y: uint256(0x08f2440e536e19058e644f53357f040c6123dc028cccec4fda5b4f030e38ea94) + x: uint256(0x06f98facee515b87d5264772d53b0eb4bd282242c5875a2fe604fb2eff7e3b51), + y: uint256(0x2f35cbbca311c61ef34f245e15afa02dd4f2e2bfdb97ae8d3deaf7637fb1b0a1) }), qo: Honk.G1Point({ - x: uint256(0x1dbe107d6bbb601e6540648740aab1cc45e94a288a20a78d6a352a79d04fc275), - y: uint256(0x2e53fd16a06904f737552331152035e335c6dd8f0017b21cbf52a340cdb6ac1f) + x: uint256(0x2fcff4b6b929edea1d8b95063f743b15fd9be8357383d75e11b1d3d23f0b8ab8), + y: uint256(0x0e8864144bfea1c7c401566b6eaef1ed13006acf6b78ad09482e60879fd3c8eb) }), q4: Honk.G1Point({ - x: uint256(0x1269f80c74d44ecdc655a54a58e1a3a08672f5cac849df0750fbad95a5600440), - y: uint256(0x1389a9781486db51b657860a0825aea9fbb52939ce4cc37fb2c7448ba6ca8e97) + x: uint256(0x209b78a4a8c8aca16be35dc1902e836f9b26963310f44b72c1c3d43b838176e1), + y: uint256(0x159828bef076d9cc71fb0a9f7f4da93f1df070666ed6507c0e288fe4df7043a3) }), qm: Honk.G1Point({ - x: uint256(0x2106f38ee711d176a0e31c843755d8bee2b3d0b09b008e72da3f3922a291a8e2), - y: uint256(0x291b9c179f0182baf30499124e134af98dd048ddd768edf3a1c1d83101f7ec00) + x: uint256(0x193e024bd335740e4b9f6a7775eca3333c818faac35ef53b0bdbd7fb30ecdd3d), + y: uint256(0x0d49ad0fe39a9edaf4d3cb0789d3057302aba3dd2aaef447c70ff1fed45a7e32) }), qc: Honk.G1Point({ - x: uint256(0x2965ca056bec0d32a078f476f1dbef37c0ba7f69512db8beef4d7a80f1e0c61c), - y: uint256(0x2fa4f0f839d6ce583dada1ea6f6ad12e5c860762df31579a2cddefd45f50a593) + x: uint256(0x186dbdf151dd0b68d86e060ef25624b0db55b25a1145d221d4b82e220528c37f), + y: uint256(0x2100edd66fd054be8971fcda53bbaeee855b73579829f4287ef08cf3ac9701b4) }), qLookup: Honk.G1Point({ x: uint256(0x111ada27d4243c5df982e1cd77f2d9aff394ba4f2ba2faf8ec1a8e5b6d78d1e7), y: uint256(0x1cf81a5fe339ef18222213e43155e149d0211317fe0a68d795681f31ef25ad0f) }), qArith: Honk.G1Point({ - x: uint256(0x300512e679e6cfe651462108d36e34fe7d8a43e3ec97a783c4c9388068e12457), - y: uint256(0x16a3ce5bee48993935216e3fa2edc60b6a288b33e5f2cd234fc9220eb7112429) + x: uint256(0x08ece1e91721cf4bfdfd0fe72b01dcf0a296f8bceb23e0f53b23334e6d90786e), + y: uint256(0x03e8a9efb8b6cdac795aed61b57f5e4db243ced17e36f395120e23225d1ddb7d) }), qDeltaRange: Honk.G1Point({ - x: uint256(0x1ab91e3b8f5c1bafc8584036f1ec35eafdc7848f87501496cd968e7b125a45b0), - y: uint256(0x26e370885ee010f8ca60ec6fc07e726364caf11898fb12421ddfede3532bd853) + x: uint256(0x1a60147b34d93b20415b95e490ea7be8dc2c3a11e0d6151c4aa0b27f2a7d8e78), + y: uint256(0x0bd085733f21156eab043e5a069932b244989e30ded0014897bbbffa92cb7b21) }), qElliptic: Honk.G1Point({ - x: uint256(0x2aeaf72123d84c2f1f09c5f4c08ee6984e4091f1568f9f6b6035ba5cd99bfc11), - y: uint256(0x2a28c9082b851a9475790e461e1e06942fc1a33dea3fb775e8f6f0174945fbf9) + x: uint256(0x09cf687c3908ee950debdd4424e183c573695401fbcafb28298cec594bd749e0), + y: uint256(0x28a95beee30f02ee547055ae480a7770e624854e6e352559567e84ba2caf204a) }), qMemory: Honk.G1Point({ - x: uint256(0x0bca7506936c66cc981136b256890b3e42a7714ea686a3b254599cead5ac1b76), - y: uint256(0x18f570d280eb8c0f0e405caf98a465655d46a09b7214c629e3cb7df65c44d3a1) + x: uint256(0x1faea00dfc82a34dd3f0b8b3710a1c6bd0aa2e33ea4dc1bb7912989d3107317d), + y: uint256(0x15a071c984d2f7e587d75a895a90212bbaed233eaa47728d7a091727071fa65b) }), qNnf: Honk.G1Point({ - x: uint256(0x12ddf7790f78e99382578be0be2b774f653f4699feb3cc75146d608c07b23cc0), - y: uint256(0x1c7aa57374e663ac28c52b9e89d85d5b43950e653a257b93ee93908ba172452a) + x: uint256(0x087b9a39420e42d9b6018916398869e864306e4cc71c4f038992095b22408bb3), + y: uint256(0x254a3a5359708f470a4dbe548e73b9639b6d434f153f7024e74a98f069bdf4f7) }), qPoseidon2External: Honk.G1Point({ - x: uint256(0x02b883bf735f0495c00706750202af048a9fb1236565dbd8a4bd9cd65d62cd45), - y: uint256(0x1df068483fd21a1324c66e3edfddf4cf262a49018d868f06137f9967a768d434) + x: uint256(0x01cc2586c0a90d6eada6829a81be823f51b800ed81921e9a7118ed6375d3ef90), + y: uint256(0x1614ad33641650bc5b0fddb1d33b1b0905ac76e314ba68643816f5ab4be5f32b) }), qPoseidon2Internal: Honk.G1Point({ - x: uint256(0x0e591142555a9892f389e3878f9c223bd6aefdb2da5fa052e9412c8a32813f59), - y: uint256(0x228b08999e84933242faba6b29da88a0d3d5bfebee3ab34ec4a3e58dffde9209) + x: uint256(0x2714df1e9e7e810b5552b5c89959d2cb3c4bd7279dc905006e5adc8aeee702ef), + y: uint256(0x2237896379a3e05feda2f73e7b3f2c448d386fb79d2dcb58993f3f843ff593e1) }), s1: Honk.G1Point({ - x: uint256(0x01c1d72a9fce26c9dd80a3e741e41cc6de658192d055ef797dd05d425ab2a60d), - y: uint256(0x2571424507bb289eb1f165fbb5d0cccd2f73a3c9655af27d65b89ee81a335eb2) + x: uint256(0x0901065fc928846a5c3ca18824b71fcf1e8255af3de10ed78bc0eb2a07c802e1), + y: uint256(0x2de55a389e7233b391480f9017e48c27cb933aef58783329f67abb97cfb3c4f7) }), s2: Honk.G1Point({ - x: uint256(0x049262a1d79e194a1787580c7592d66a8276b129379e3215d2cf1e76245f5f5d), - y: uint256(0x0015a76d65bfb1bc143f558a48a0396305275edd989bae9ababc97c932df9a7f) + x: uint256(0x0dce58adbf68bb4d24b2cb12225fbb7ea87b75fa1bf4b191f9156eed6cd118c8), + y: uint256(0x1119b21af9e60ab4ed8a053142ffba8729ad596a42f0a897f5e7f0fe443ab6d1) }), s3: Honk.G1Point({ - x: uint256(0x2368a0e09e8963f9e6e1ea99e6ac4d412af1c30962ca6e5dd45fb405753ed53e), - y: uint256(0x07a32010169e8592f4f4b7c9dbc6a617859acdd13b4ad329bf6ca5b385b3c3ea) + x: uint256(0x29c0dac401bb440653c13bfe5b2a7f533bcbeff32197ea0689c87a1b1d8d3243), + y: uint256(0x1fcb8593d6a7646cfdf79d0356ac6cd3490e37d9e3c1e63d6f699138d8047862) }), s4: Honk.G1Point({ - x: uint256(0x29ab00032fef2aba36b00340b4690ced045e22811e62fd7b2bf7e2ecc83b8996), - y: uint256(0x2293b532735e839c9c0d9658f75145c0a71f00d9143fb0bdbf9bad99ed811308) + x: uint256(0x300e30489aeb10e362e7f22fd9937bb1bcf48134a5b7f30eb543f24c7b73e196), + y: uint256(0x20e75d26db3654395e2a6d098259dad7b3b2eb704b1a1b89027ed954a055f0de) }), t1: Honk.G1Point({ x: uint256(0x1f16b037f0b4c96ea2a30a118a44e139881c0db8a4d6c9fde7db5c1c1738e61f), @@ -104,28 +104,28 @@ library HonkVerificationKey { y: uint256(0x2d7e8c1ecb92e2490049b50efc811df63f1ca97e58d5e82852dbec0c29715d71) }), id1: Honk.G1Point({ - x: uint256(0x0f763a39c7f1d60c34ffd472e45528e457d514a647c4aab115ff131b88fcf78b), - y: uint256(0x0d8784fb3171af6e6dd0c199eb2a1b9d8e4a989e12cf8aed9827a42ede7bb472) + x: uint256(0x016533e08fe7e63f5937efd35c053f1d285c0c3641941ef8549f7111475b2b48), + y: uint256(0x280345c9954e0411ced2a0047f7896a991c2dd9ef8cd71c498dd9006183a6552) }), id2: Honk.G1Point({ - x: uint256(0x23c5218d4ca0a7973ff8355621a7ea8c074e6ce5f2b45c3cbf35805a7c4f8e06), - y: uint256(0x234dfd63fe6fd61f2414c254cb4c9632dbf49696cb1e9b01c681336dd0ec070d) + x: uint256(0x014eb30843d99be05cc9a65cca85350936000ebe851df702424750d8ba3eefb3), + y: uint256(0x005b877c1222731bcef28ebe51c015e282d9822e5355584765c4b3d433da3bd7) }), id3: Honk.G1Point({ - x: uint256(0x02b0c39f64b037a63141f38b238f184b9c9f3c42496f92ef699f1c4e233c3762), - y: uint256(0x2d3e477b946ebdc896aad38a7f226c98b8fc32ad79522512948d1a22b491cea5) + x: uint256(0x105390d6f0c9c55ae11af6da3b7b096d024e24306e347a9e09fd3a1387b4adac), + y: uint256(0x0f2f04a199fe491694caf93e3502919c4d42c6fa4ec6e7519930de754bf7e449) }), id4: Honk.G1Point({ - x: uint256(0x27fe3dbc937a376a1c3f13470a4c8cc06aff2d1de9076059876150b7274be830), - y: uint256(0x102d1f66d257589a309544e8857e925c71f7f17706480014e3307783a67914ba) + x: uint256(0x2400c1703add89e06b7dbb4db20cfe3b821b2b30202a5ccf143eccf12f21da2f), + y: uint256(0x107524fede03fc1cd700efc0be3a5d8cc6f967de3765217d99e3c8b0cc8415a8) }), lagrangeFirst: Honk.G1Point({ x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) }), lagrangeLast: Honk.G1Point({ - x: uint256(0x0abc96b13980d69bf46819cc4b5008a18a549b52251ae0ef596f13e9149f2c31), - y: uint256(0x0301acf167c28438e607bcc3fc7c29b802b1f9787f24c29e13db0a03528f3a9c) + x: uint256(0x1654162a2d2b8fff1690509e5ffb19ffc51d4139653da0d23130536d88772453), + y: uint256(0x2e00da8af6c5abf721b41071479ff1fdf35e930437c6e0ae1715a5a3aa9c90a7) }) }); return vk; diff --git a/examples/CRISP/packages/crisp-sdk/src/types.ts b/examples/CRISP/packages/crisp-sdk/src/types.ts index 199eca67b8..5bd914b44b 100644 --- a/examples/CRISP/packages/crisp-sdk/src/types.ts +++ b/examples/CRISP/packages/crisp-sdk/src/types.ts @@ -163,6 +163,8 @@ export type CircuitInputs = { balance: string // Whether this is the first vote for this slot. is_first_vote: boolean + // Whether this is a mask vote. + is_mask_vote: boolean } export type ProofData = { @@ -185,6 +187,7 @@ export type ProofInputs = { balance: bigint slotAddress: string merkleProof: MerkleProof + isMaskVote: boolean } export type MaskVoteProofInputs = { diff --git a/examples/CRISP/packages/crisp-sdk/src/vote.ts b/examples/CRISP/packages/crisp-sdk/src/vote.ts index 28106263dc..811b29c636 100644 --- a/examples/CRISP/packages/crisp-sdk/src/vote.ts +++ b/examples/CRISP/packages/crisp-sdk/src/vote.ts @@ -203,6 +203,7 @@ export const generateCircuitInputs = async ( crispInputs.slot_address = proofInputs.slotAddress.toLowerCase() crispInputs.balance = proofInputs.balance.toString() crispInputs.is_first_vote = !proofInputs.previousCiphertext + crispInputs.is_mask_vote = proofInputs.isMaskVote crispInputs.merkle_root = proofInputs.merkleProof.proof.root.toString() crispInputs.merkle_proof_length = proofInputs.merkleProof.length.toString() crispInputs.merkle_proof_indices = proofInputs.merkleProof.indices.map((i) => i.toString()) @@ -270,6 +271,7 @@ export const generateVoteProof = async (voteProofInputs: VoteProofInputs): Promi previousCiphertext: voteProofInputs.previousCiphertext, signature: voteProofInputs.signature, messageHash: voteProofInputs.messageHash, + isMaskVote: false, }) return { ...(await generateProof(crispInputs)), encryptedVote } @@ -289,6 +291,7 @@ export const generateMaskVoteProof = async (maskVoteProofInputs: MaskVoteProofIn messageHash: SIGNATURE_MESSAGE_HASH, vote: ZERO_VOTE, merkleProof, + isMaskVote: true, }) return { ...(await generateProof(crispInputs)), encryptedVote } diff --git a/examples/CRISP/packages/crisp-sdk/tests/vote.test.ts b/examples/CRISP/packages/crisp-sdk/tests/vote.test.ts index 0d516c285d..aa6daf66b8 100644 --- a/examples/CRISP/packages/crisp-sdk/tests/vote.test.ts +++ b/examples/CRISP/packages/crisp-sdk/tests/vote.test.ts @@ -123,6 +123,7 @@ describe('Vote', () => { balance, slotAddress: address, merkleProof, + isMaskVote: false, }) const { returnValue } = await executeCircuit(crispInputs) @@ -146,6 +147,7 @@ describe('Vote', () => { signature: MASK_SIGNATURE, messageHash: SIGNATURE_MESSAGE_HASH, previousCiphertext, + isMaskVote: true, }) const { returnValue } = await executeCircuit(crispInputs) @@ -168,6 +170,7 @@ describe('Vote', () => { merkleProof, balance, slotAddress, + isMaskVote: true, }) const { returnValue } = await executeCircuit(crispInputs) diff --git a/examples/CRISP/server/.env.example b/examples/CRISP/server/.env.example index 7fcffc68b3..04fc28623a 100644 --- a/examples/CRISP/server/.env.example +++ b/examples/CRISP/server/.env.example @@ -23,7 +23,7 @@ FEE_TOKEN_ADDRESS="0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" E3_WINDOW_SIZE=30 # Defines the time interval during which users can submit their inputs # After this interval, the computation phase starts automatically -E3_DURATION=60 +E3_DURATION=70 E3_THRESHOLD_MIN=2 E3_THRESHOLD_MAX=5