From f31a5a6e93ff56c6195aa646f9ecf3ebd891d30c Mon Sep 17 00:00:00 2001 From: 99Kies <1290017556@qq.com> Date: Sat, 18 Jul 2026 16:14:43 +0800 Subject: [PATCH 1/6] feat: add max_votes_per_option support to amaci circuits, sdk and contracts - add maxVotesPerOption signal to messageValidator/stateLeafTransformer/processMessages circuits (amaci/power) - pack maxVotesPerOption into the 4th 32-bit slot of packedVals (bits 96-127), 0 = unlimited (backward compatible) - sdk: operator.ts/voter.ts/contract.ts support configuring and validating maxVotesPerOption - contracts: amaci/registry/api-saas msg/state/contract updated to store, validate and query max_votes_per_option - regenerate test-scale (2-1-1-5) zkey/vkey and logs.json fixtures to match the updated circuits - add circuit unit tests (MessageValidator/StateLeafTransformer/ProcessMessages) and a full-round contract test driven by real generated proofs - fix generate-logs.ts: REQUIRED_REMOTE_ARTIFACTS was evaluated at module load before its referenced vars were assigned NOTE: production-scale (9-4-3-125) vkey/zkey has NOT been regenerated; a real trusted setup ceremony is still required before this can be deployed to production rounds. --- contracts/amaci/src/circuit_params.rs | 12 +- contracts/amaci/src/contract.rs | 40 +- contracts/amaci/src/error.rs | 3 + contracts/amaci/src/msg.rs | 9 + contracts/amaci/src/multitest/mod.rs | 4 + contracts/amaci/src/multitest/tests.rs | 462 +++++++++++++++- contracts/amaci/src/state.rs | 2 + contracts/amaci/src/test/amaci_test/logs.json | 182 ++++--- contracts/api-saas/src/contract.rs | 4 + contracts/api-saas/src/msg.rs | 4 + contracts/api-saas/src/multitest/mod.rs | 1 + contracts/registry/src/contract.rs | 4 + contracts/registry/src/msg.rs | 4 + contracts/registry/src/multitest/mod.rs | 6 + .../registry/src/test/amaci_test/logs.json | 182 ++++--- e2e/circuits/vkeys-amaci-2-1-1-5.json | 14 +- .../amaci/power/messageValidator.circom | 24 +- .../circom/amaci/power/processMessages.circom | 22 +- .../amaci/power/stateLeafTransformer.circom | 2 + packages/circuits/circom/circuits.json | 36 -- .../DeactivateStatusDetection.test.ts | 1 + .../__tests__/MessageValidatorAmaci.test.ts | 485 ++++++++++++----- ...cessMessagesAmaciMaxVotesPerOption.test.ts | 252 +++++++++ .../StateLeafTransformerAmaci.test.ts | 513 ++++++++++++------ packages/circuits/ts/generate-logs.ts | 141 +++-- packages/sdk/src/libs/contract/contract.ts | 2 + packages/sdk/src/libs/contract/types.ts | 2 + packages/sdk/src/operator.ts | 24 +- packages/sdk/src/voter.ts | 18 + 29 files changed, 1866 insertions(+), 589 deletions(-) create mode 100644 packages/circuits/ts/__tests__/ProcessMessagesAmaciMaxVotesPerOption.test.ts diff --git a/contracts/amaci/src/circuit_params.rs b/contracts/amaci/src/circuit_params.rs index 2ee3fe74..e342c387 100644 --- a/contracts/amaci/src/circuit_params.rs +++ b/contracts/amaci/src/circuit_params.rs @@ -44,9 +44,9 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "14fcf460ec67f39e7604ce59622a530797f70d5dce2cdbfcc6285acb11a091490a51cc6cc5aec73e4b1fcd45f152e8d18d9831efa2ca2d8aba5ec00a5258a86c2588c3053fe7907bd6e3b3b455283a441df9f5e9cc8b1aca6712d37004c28e4311915d144397caf4c4e74e150159574574d84d4a620cc22e1ee695b45f0c09fb".to_string(), - vk_ic0: "152b83fbeccaaf60ff7c47ebcefc9368d1d81271fc47d36e3032f589112849c900ce96219b641b39a390c8fe58b8ff805e21e55257e1437c26285d030fb52a70".to_string(), - vk_ic1: "0722c7bc6aaf03f86fc32096b9ad50fa14a99d113cd02d3a26df629703f7b9b61a19f057b25b77efefe232bb2cc87d9637bca988fc0325bd8c9e4b1febe5eca4".to_string(), + vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), + vk_ic0: "2109d20e2dfb65b2564cdd873f95f21a9215d9757c6ec62637b8d80373e1e9bb066ef0037b411d062439a5034b5c71bcdc2df0e3999fe5b7afd7cb88a32ceb30".to_string(), + vk_ic1: "05199f9ffa6b1ec953808a3dd750ad9168ae7a1464ddcead6cf31d61530e22a215b34e716a4871c189f25cf43ebc656d3256812cb98179183df2a9da65da34b9".to_string(), }; let groth16_process_vkeys = format_vkey(&groth16_process_vkey)?; @@ -54,7 +54,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "21770a545c0aaa828d45a00c7335a689ac65650edb60d582ae66928eb860ac8811ec3ee19549dc6bf84515db12f782b7c6848fe4d004d32a5d27bce19440c34a173c6f347154f90a6052e1ca1faf89d4940527f248597c340c5c6cdf436225342c0fa0a92e84c22bb553aa427aa53c0f5f3ba7f7d223f6eb89b7d7cba26eb070".to_string(), + vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), vk_ic0: "0b20a7584a8679cc6cf8e8cffc41ce9ad79c2cd0086214c3cb1af12146916bb9185b916c9938601b30c6fc4e7f2e1f1a7a94cb81e1774cb1f67b54eb33477e82".to_string(), vk_ic1: "081919adecf04dd5e1c31a3e34f8907d2ca613df81f99b3aa56c5027cd6416c201ddf039c717b1d29ecc2381db6104506731132f624e60cc09675a100028de25".to_string(), }; @@ -64,7 +64,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "0b2b685a254c97378d11100e45db341efebcc5e3d026fe920fdf1cac04c5feb4135b02f250b191e658c55341d45184bde62cec70444c4f210fdb507d5622dc821fe7bc3e41c31a4e6b7288ca0d519b80b18e722712d24f8786155d683f0bff7101e736bd668785e26ceb252106aaa784c922e2509d37444c711da6b3d8d0c8ad".to_string(), + vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), vk_ic0: "141ed95aed8eac95334e6dbaa513736949402fd820920d8e2179d7be54593f60070ffd76988c62dbf2cf4a365da0fbecde7e7ccb39f1e0e0728a6941da3435cd".to_string(), vk_ic1: "2c1289b05f9093a1d4c7536093702b08d57654fae20ae871de2598565c43c8611d5bc6caad360c2b6f68480aa71efbcc506524104152bb73f79d9cb0f3d12180".to_string(), }; @@ -74,7 +74,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "2b135a96b33686a78339372bd40e3bef10aea0554c15a4770aeecdea0ce74b65265875823bf58d64d42fdf4ab9b8dba0a8b71dc2c1a140c68069d013a661c6a4150290c14390c9f212516d006b2b67012db77104bb20f3b980e924069a27c725119f442673a5ead331dfdfbbb1963ff41eca2f0a518e535f7b6b44cea1efd3df".to_string(), + vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), vk_ic0: "29639aea06acd9b07e36d2456153d4e81581d65efb2fc93f0d54618398be1c471f49496bce6f344badecd9493d07faaaa2d09c7216734488f3ce2e2d0bd25be9".to_string(), vk_ic1: "20ccb32cbbbb10099ab8ef2bfd196ec22b3c07c8c7eba7076bb8d16be4aa69ad0b0ff4e2a298219ef216024cd65a8b26470a7daa2e8ce55af41038a74d5d589f".to_string(), }; diff --git a/contracts/amaci/src/contract.rs b/contracts/amaci/src/contract.rs index 662f22d7..57b50df5 100644 --- a/contracts/amaci/src/contract.rs +++ b/contracts/amaci/src/contract.rs @@ -16,7 +16,8 @@ use crate::state::{ DMSG_CHAIN_LENGTH, DMSG_HASHES, DNODES, FEE_CONFIG, FEE_DENOM, FEE_RECIPIENT, FIRST_DMSG_TIMESTAMP, GROTH16_DEACTIVATE_VKEYS, GROTH16_NEWKEY_VKEYS, GROTH16_PROCESS_VKEYS, GROTH16_TALLY_VKEYS, LEAF_IDX_0, MACIPARAMETERS, MACI_OPERATOR, - MAX_LEAVES_COUNT, MAX_VOTE_OPTIONS, MSG_CHAIN_LENGTH, MSG_HASHES, NODES, NULLIFIERS, + MAX_LEAVES_COUNT, MAX_VOTES_PER_OPTION, MAX_VOTE_OPTIONS, MSG_CHAIN_LENGTH, MSG_HASHES, NODES, + NULLIFIERS, NUMSIGNUPS, ORACLE_WHITELIST, PENALTY_RATE, PERIOD, POLL_ID, PRE_DEACTIVATE_COORDINATOR_HASH, PRE_DEACTIVATE_ROOT, PROCESSED_DMSG_COUNT, PROCESSED_MSG_COUNT, PROCESSED_USER_COUNT, QTR_LIB, REGISTRATION_MODE, RESULT, ROUNDINFO, SIGNUPED, STATE_ROOT_BY_DMSG, @@ -550,6 +551,16 @@ pub fn instantiate( &Uint256::from_u128(msg.vote_option_map.len() as u128), )?; + // Per-option vote weight cap (0 = no limit). Must fit in the 32-bit + // packedVals slot consumed by the process circuit. + let max_votes_per_option = msg.max_votes_per_option.unwrap_or(Uint256::zero()); + if max_votes_per_option >= Uint256::from_u128(1u128 << 32) { + return Err(ContractError::MaxVotesPerOptionExceeded { + current: max_votes_per_option, + }); + } + MAX_VOTES_PER_OPTION.save(deps.storage, &max_votes_per_option)?; + // ============================================ // Process Voice Credit Mode Configuration // ============================================ @@ -720,6 +731,7 @@ pub fn instantiate( attr("coordinator_pubkey_x", &msg.coordinator.x.to_string()), attr("coordinator_pubkey_y", &msg.coordinator.y.to_string()), attr("max_vote_options", &msg.vote_option_map.len().to_string()), + attr("max_votes_per_option", &max_votes_per_option.to_string()), attr( "state_tree_depth", &msg.parameters.state_tree_depth.to_string(), @@ -1989,18 +2001,19 @@ pub fn execute_process_message( let num_sign_ups = NUMSIGNUPS.load(deps.storage)?; let max_vote_options = MAX_VOTE_OPTIONS.load(deps.storage)?; + let max_votes_per_option = MAX_VOTES_PER_OPTION + .may_load(deps.storage)? + .unwrap_or(Uint256::zero()); let circuit_type = CIRCUITTYPE.load(deps.storage)?; - if circuit_type == Uint256::from_u128(0u128) { - // 1p1v - input[0] = (num_sign_ups << 32) + max_vote_options; // packedVals - } else if circuit_type == Uint256::from_u128(1u128) { - // qv - input[0] = (num_sign_ups << 32) + (circuit_type << 64) + max_vote_options; - // packedVals - } - - // input[0] = (num_sign_ups << 32) + max_vote_options; // packedVals + // packedVals layout (32-bit slots, low to high): + // bits 0-31: maxVoteOptions, bits 32-63: numSignUps, + // bits 64-95: isQuadraticCost, bits 96-127: maxVotesPerOption + // circuit_type is 0 (1p1v) or 1 (qv), so shifting it directly is safe. + input[0] = (max_votes_per_option << 96) + + (circuit_type << 64) + + (num_sign_ups << 32) + + max_vote_options; // Load the coordinator's public key hash let coordinator_hash = COORDINATORHASH.load(deps.storage)?; @@ -2671,6 +2684,11 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { QueryMsg::MaxVoteOptions {} => { to_json_binary::(&MAX_VOTE_OPTIONS.may_load(deps.storage)?.unwrap_or_default()) } + QueryMsg::MaxVotesPerOption {} => to_json_binary::( + &MAX_VOTES_PER_OPTION + .may_load(deps.storage)? + .unwrap_or_default(), + ), QueryMsg::QueryCircuitType {} => { to_json_binary::(&CIRCUITTYPE.may_load(deps.storage)?.unwrap_or_default()) } diff --git a/contracts/amaci/src/error.rs b/contracts/amaci/src/error.rs index edd094a7..36999dec 100644 --- a/contracts/amaci/src/error.rs +++ b/contracts/amaci/src/error.rs @@ -93,6 +93,9 @@ pub enum ContractError { max_allowed: Uint256, }, + #[error("max_votes_per_option must fit in 32 bits, current value is {current}.")] + MaxVotesPerOptionExceeded { current: Uint256 }, + #[error("Unsupported circuit type.")] UnsupportedCircuitType {}, diff --git a/contracts/amaci/src/msg.rs b/contracts/amaci/src/msg.rs index 053b1548..31c941d0 100644 --- a/contracts/amaci/src/msg.rs +++ b/contracts/amaci/src/msg.rs @@ -22,6 +22,12 @@ pub struct InstantiateMsg { pub round_info: RoundInfo, pub voting_time: VotingTime, + // Per-option vote weight cap enforced by the process circuit. + // None or 0 = no limit (legacy behavior). Must fit in 32 bits + // (packedVals slot width). serde(default) keeps old JSON payloads valid. + #[serde(default)] + pub max_votes_per_option: Option, + // Circuit configuration pub circuit_type: Uint256, // <0: 1p1v | 1: pv> pub certification_system: Uint256, // <0: groth16 | 1: plonk> @@ -259,6 +265,9 @@ pub enum QueryMsg { #[returns(Uint256)] MaxVoteOptions {}, + #[returns(Uint256)] + MaxVotesPerOption {}, + #[returns(Uint256)] QueryCircuitType {}, diff --git a/contracts/amaci/src/multitest/mod.rs b/contracts/amaci/src/multitest/mod.rs index 5adc4c2f..beb1c0bf 100644 --- a/contracts/amaci/src/multitest/mod.rs +++ b/contracts/amaci/src/multitest/mod.rs @@ -407,6 +407,7 @@ impl MaciContract { signup_delay: PER_SIGNUP_DELAY, deactivate_delay: DEACTIVATE_DELAY, deactivate_enabled: false, // Default: disabled + max_votes_per_option: None, }; app.instantiate_contract( @@ -479,6 +480,7 @@ impl MaciContract { signup_delay: PER_SIGNUP_DELAY, deactivate_delay: DEACTIVATE_DELAY, deactivate_enabled: true, // ENABLED for deactivate and add_new_key tests + max_votes_per_option: None, }; app.instantiate_contract( @@ -1501,6 +1503,7 @@ impl MaciContract { signup_delay: PER_SIGNUP_DELAY, deactivate_delay: DEACTIVATE_DELAY, deactivate_enabled: false, // Default: disabled + max_votes_per_option: None, }; app.instantiate_contract( @@ -1638,6 +1641,7 @@ impl MaciContract { signup_delay: PER_SIGNUP_DELAY, deactivate_delay: DEACTIVATE_DELAY, deactivate_enabled: true, // ENABLED! + max_votes_per_option: None, }; app.instantiate_contract( diff --git a/contracts/amaci/src/multitest/tests.rs b/contracts/amaci/src/multitest/tests.rs index c4d110cc..9e29bcbf 100644 --- a/contracts/amaci/src/multitest/tests.rs +++ b/contracts/amaci/src/multitest/tests.rs @@ -8,10 +8,10 @@ mod test { }; use crate::multitest::certificate_generator::generate_certificate_for_pubkey; use crate::multitest::{ - create_app, owner, test_oracle_pubkey, test_pubkey1, test_pubkey2, test_pubkey3, - uint256_from_decimal_string, user1, user2, user3, BASE_DELAY, DEACTIVATE_DELAY, - DEACTIVATE_FEE, MESSAGE_FEE, PER_MESSAGE_DELAY, PER_SIGNUP_DELAY, SIGNUP_FEE, MaciCodeId, - MaciContract, + create_app, fee_recipient, operator, owner, test_oracle_pubkey, test_pubkey1, + test_pubkey2, test_pubkey3, uint256_from_decimal_string, user1, user2, user3, BASE_DELAY, + DEACTIVATE_DELAY, DEACTIVATE_FEE, MESSAGE_FEE, PER_MESSAGE_DELAY, PER_SIGNUP_DELAY, + SIGNUP_FEE, MaciCodeId, MaciContract, }; use crate::state::{ DelayRecord, DelayRecords, DelayType, MaciParameters, MessageData, Period, PeriodStatus, @@ -119,13 +119,23 @@ mod test { new_deactivate_root: String, } + /// Matches the shape written by `generate-logs.ts` (via the SDK's + /// `adaptToUncompressed`): each component is already a single hex string + /// (uncompressed G1/G2 point encoding), i.e. exactly what `Groth16ProofType` + /// expects. No further conversion is needed beyond field renaming. #[derive(Debug, Serialize, Deserialize)] struct Groth16Proof { - pi_a: Vec, - pi_b: Vec>, - pi_c: Vec, - protocol: String, - curve: String, + pi_a: String, + pi_b: String, + pi_c: String, + } + + fn to_groth16_proof_type(proof: &Groth16Proof) -> Groth16ProofType { + Groth16ProofType { + a: proof.pi_a.clone(), + b: proof.pi_b.clone(), + c: proof.pi_c.clone(), + } } #[derive(Debug, Serialize, Deserialize)] @@ -2236,6 +2246,140 @@ mod test { assert_eq!(enabled, false, "Deactivate should be disabled by default"); } + fn max_votes_per_option_init_msg(max_votes_per_option: Option) -> InstantiateMsg { + InstantiateMsg { + parameters: MaciParameters { + state_tree_depth: Uint256::from_u128(2u128), + int_state_tree_depth: Uint256::from_u128(1u128), + message_batch_size: Uint256::from_u128(5u128), + vote_option_tree_depth: Uint256::from_u128(1u128), + }, + coordinator: PubKey { + x: uint256_from_decimal_string( + "3557592161792765812904087712812111121909518311142005886657252371904276697771", + ), + y: uint256_from_decimal_string( + "4363822302427519764561660537570341277214758164895027920046745209970137856681", + ), + }, + vote_option_map: vec!["A".to_string(), "B".to_string()], + round_info: RoundInfo { + title: "MaxVotesPerOption Test".to_string(), + description: "".to_string(), + link: "".to_string(), + }, + voting_time: VotingTime { + start_time: Timestamp::from_nanos(1571797424879000000), + end_time: Timestamp::from_nanos(1571797424879000000).plus_minutes(11), + }, + circuit_type: Uint256::from_u128(0), + certification_system: Uint256::from_u128(0), + operator: operator(), + admin: owner(), + fee_recipient: fee_recipient(), + poll_id: 1u64, + voice_credit_mode: VoiceCreditMode::Unified { + amount: Uint256::from_u128(100u128), + }, + registration_mode: RegistrationModeConfig::SignUpWithStaticWhitelist { + whitelist: WhitelistBase { users: vec![] }, + }, + message_fee: MESSAGE_FEE, + deactivate_fee: DEACTIVATE_FEE, + signup_fee: SIGNUP_FEE, + base_delay: BASE_DELAY, + message_delay: PER_MESSAGE_DELAY, + signup_delay: PER_SIGNUP_DELAY, + deactivate_delay: DEACTIVATE_DELAY, + deactivate_enabled: false, + max_votes_per_option, + } + } + + #[test] + fn test_max_votes_per_option_instantiate_and_query() { + let mut app = create_app(); + let code_id = MaciCodeId::store_code(&mut app); + + // With an explicit cap + let contract_addr = app + .instantiate_contract( + code_id.id(), + owner(), + &max_votes_per_option_init_msg(Some(Uint256::from_u128(10u128))), + &[], + "MaxVotesPerOption", + None, + ) + .unwrap(); + + let cap: Uint256 = app + .wrap() + .query_wasm_smart(contract_addr, &QueryMsg::MaxVotesPerOption {}) + .unwrap(); + assert_eq!(cap, Uint256::from_u128(10u128)); + } + + #[test] + fn test_max_votes_per_option_defaults_to_zero() { + let mut app = create_app(); + let code_id = MaciCodeId::store_code(&mut app); + + // Omitted (None) => stored as 0 (no limit) + let contract_addr = app + .instantiate_contract( + code_id.id(), + owner(), + &max_votes_per_option_init_msg(None), + &[], + "MaxVotesPerOptionDefault", + None, + ) + .unwrap(); + + let cap: Uint256 = app + .wrap() + .query_wasm_smart(contract_addr, &QueryMsg::MaxVotesPerOption {}) + .unwrap(); + assert_eq!(cap, Uint256::zero()); + } + + #[test] + fn test_max_votes_per_option_rejects_over_32_bits() { + let mut app = create_app(); + let code_id = MaciCodeId::store_code(&mut app); + + // 2^32 does not fit in the 32-bit packedVals slot => rejected + let err = app + .instantiate_contract( + code_id.id(), + owner(), + &max_votes_per_option_init_msg(Some(Uint256::from_u128(1u128 << 32))), + &[], + "MaxVotesPerOptionOverflow", + None, + ) + .unwrap_err(); + + assert_eq!( + ContractError::MaxVotesPerOptionExceeded { + current: Uint256::from_u128(1u128 << 32), + }, + err.downcast().unwrap() + ); + + // Max 32-bit value is accepted + app.instantiate_contract( + code_id.id(), + owner(), + &max_votes_per_option_init_msg(Some(Uint256::from_u128((1u128 << 32) - 1))), + &[], + "MaxVotesPerOptionBoundary", + None, + ) + .unwrap(); + } + #[test] fn test_publish_deactivate_message_disabled() { let mut app = create_app(); @@ -3125,6 +3269,7 @@ mod test { signup_delay: PER_SIGNUP_DELAY, deactivate_delay: DEACTIVATE_DELAY, deactivate_enabled: false, + max_votes_per_option: None, }; let contract_addr = app @@ -3995,6 +4140,305 @@ mod test { ); } + /// End-to-end happy-path test that replays every entry of + /// `amaci_test/logs.json` (generated by `generate-logs.ts` from the actual, + /// locally-compiled circuits) through the real contract, using the REAL + /// Groth16 proofs contained in the fixture (not hardcoded/stale bytes). + /// + /// This is the primary regression test for the `maxVotesPerOption` circuit + /// change: it exercises `ProcessDeactivateMessage`, `AddNewKey`, + /// `PublishMessage`, `ProcessMessage`, `ProcessTally` and + /// `StopTallyingPeriod` end-to-end against the current on-chain vkeys + /// (`vkeys_2_1_1_5`), confirming that circuit / vkey / logs fixture are + /// all mutually consistent after regenerating the zkeys. + #[test] + fn test_amaci_full_round_verifies_real_proofs_from_generated_logs() { + use cosmwasm_std::coins; + + // NOTE: deliberately NOT read from `./src/test/user_pubkey.json` — that + // fixture belongs to an unrelated, older test dataset and does not match + // the voter secret keys (222222n / 555555n) used by `generate-logs.ts` to + // build `amaci_test/logs.json`. Using it here would build an on-chain state + // tree whose root doesn't match `currentStateRoot`/`newStateCommitment` + // baked into the real proofs below (verification would fail). + let pubkey0 = PubKey { + x: uint256_from_decimal_string( + "17399497775960102380565502463631688556400670056228730095262963787053279532078", + ), + y: uint256_from_decimal_string( + "18877551448216649826981805566855898133402281419471365959781518735588655366005", + ), + }; + let pubkey1 = PubKey { + x: uint256_from_decimal_string( + "13803433674260555137344899799385392014418808114966341658474816997307159870057", + ), + y: uint256_from_decimal_string( + "11777832779674825198240044994151418890710853633023664547951328846960155271963", + ), + }; + + let logs_file_path = "./src/test/amaci_test/logs.json"; + let mut logs_file = fs::File::open(logs_file_path).expect("Failed to open logs.json"); + let mut logs_content = String::new(); + logs_file + .read_to_string(&mut logs_content) + .expect("Failed to read file"); + let logs_data: Vec = + serde_json::from_str(&logs_content).expect("Failed to parse JSON"); + + let mut app = create_app(); + let code_id = MaciCodeId::store_code(&mut app); + + // NOTE: unlike the `instantiate_with_voting_time_isqv_amaci` helper (which + // hardcodes an unrelated `test_pubkey1()` as the coordinator), the coordinator + // pubkey here MUST match the operator secret key (111111n) used by + // `generate-logs.ts`, since the circuit's public inputHash commits to the + // coordinator pubkey hash. A mismatched coordinator would make every proof + // fail verification regardless of correctness. + let coordinator_pubkey = PubKey { + x: uint256_from_decimal_string( + "1421543221206310383340195030620766117814469350837741893103919053409918312818", + ), + y: uint256_from_decimal_string( + "5844095285348097514075616375079349318227570502756036806774906942110501360620", + ), + }; + let init_msg = InstantiateMsg { + parameters: MaciParameters { + state_tree_depth: Uint256::from_u128(2u128), + int_state_tree_depth: Uint256::from_u128(1u128), + message_batch_size: Uint256::from_u128(5u128), + vote_option_tree_depth: Uint256::from_u128(1u128), + }, + coordinator: coordinator_pubkey, + vote_option_map: vec![ + "Option 1".to_string(), + "Option 2".to_string(), + "Option 3".to_string(), + "Option 4".to_string(), + "Option 5".to_string(), + ], + round_info: RoundInfo { + title: String::from("full-round-verify"), + description: String::from("full-round-verify"), + link: String::from("https://baidu.com"), + }, + voting_time: VotingTime { + start_time: Timestamp::from_nanos(1571797424879000000), + end_time: Timestamp::from_nanos(1571797424879000000).plus_minutes(11), + }, + circuit_type: Uint256::from_u128(1u128), + certification_system: Uint256::from_u128(0u128), + operator: operator(), + admin: owner(), + fee_recipient: fee_recipient(), + poll_id: 1u64, + voice_credit_mode: VoiceCreditMode::Unified { + amount: Uint256::from_u128(100u128), + }, + registration_mode: RegistrationModeConfig::SignUpWithStaticWhitelist { + whitelist: WhitelistBase { + users: vec![ + WhitelistBaseConfig { addr: user1(), voice_credit_amount: None }, + WhitelistBaseConfig { addr: user2(), voice_credit_amount: None }, + WhitelistBaseConfig { addr: user3(), voice_credit_amount: None }, + ], + }, + }, + message_fee: MESSAGE_FEE, + deactivate_fee: DEACTIVATE_FEE, + signup_fee: SIGNUP_FEE, + base_delay: BASE_DELAY, + message_delay: PER_MESSAGE_DELAY, + signup_delay: PER_SIGNUP_DELAY, + deactivate_delay: DEACTIVATE_DELAY, + deactivate_enabled: true, + max_votes_per_option: None, + }; + let contract_addr = app + .instantiate_contract( + u64::from(code_id), + owner(), + &init_msg, + &[], + "full-round-verify-test", + None, + ) + .expect("instantiate must succeed"); + let contract = MaciContract::new(contract_addr); + + _ = contract.set_vote_option_map(&mut app, owner()); + app.update_block(next_block); // Start Voting + + contract + .sign_up(&mut app, user1(), pubkey0) + .expect("sign_up user1 must succeed"); + contract + .sign_up(&mut app, user2(), pubkey1) + .expect("sign_up user2 must succeed"); + assert_eq!( + contract.num_sign_up(&app).unwrap(), + Uint256::from_u128(2u128) + ); + + let mut expected_results: Vec = Vec::new(); + + for entry in &logs_data { + match entry.log_type.as_str() { + "publishDeactivateMessage" => { + let data: PublishDeactivateMessageData = deserialize_data(&entry.data); + let mut msg_data = [Uint256::from_u128(0u128); 10]; + for (i, v) in data.message.iter().enumerate().take(10) { + msg_data[i] = uint256_from_decimal_string(v); + } + let message = MessageData { data: msg_data }; + let enc_pub = PubKey { + x: uint256_from_decimal_string(&data.enc_pub_key[0]), + y: uint256_from_decimal_string(&data.enc_pub_key[1]), + }; + app.execute_contract( + user2(), + contract.addr(), + &ExecuteMsg::PublishDeactivateMessage { + message, + enc_pub_key: enc_pub, + }, + &coins(DEACTIVATE_FEE.u128(), "peaka"), + ) + .expect("PublishDeactivateMessage must succeed"); + } + "proofDeactivate" => { + let data: ProofDeactivateData = deserialize_data(&entry.data); + + let size = uint256_from_decimal_string(&data.size); + let new_deactivate_commitment = + uint256_from_decimal_string(&data.new_deactivate_commitment); + let new_deactivate_root = + uint256_from_decimal_string(&data.new_deactivate_root); + let proof = to_groth16_proof_type(&data.proof); + + contract + .process_deactivate_message( + &mut app, + owner(), + size, + new_deactivate_commitment, + new_deactivate_root, + proof, + ) + .expect("ProcessDeactivateMessage with real proof must succeed"); + } + "proofAddNewKey" => { + let data: ProofAddNewKeyData = deserialize_data(&entry.data); + + let new_key_pub = PubKey { + x: uint256_from_decimal_string(&data.pub_key[0]), + y: uint256_from_decimal_string(&data.pub_key[1]), + }; + let d: [Uint256; 4] = [ + uint256_from_decimal_string(&data.d[0]), + uint256_from_decimal_string(&data.d[1]), + uint256_from_decimal_string(&data.d[2]), + uint256_from_decimal_string(&data.d[3]), + ]; + let nullifier = uint256_from_decimal_string(&data.nullifier); + let proof = to_groth16_proof_type(&data.proof); + + contract + .add_key(&mut app, owner(), new_key_pub, nullifier, d, proof) + .expect("AddNewKey with real proof must succeed"); + } + "publishMessage" => { + let data: PublishMessageData = deserialize_data(&entry.data); + + let mut msg_data = [Uint256::from_u128(0u128); 10]; + for (i, v) in data.message.iter().enumerate().take(10) { + msg_data[i] = uint256_from_decimal_string(v); + } + let message = MessageData { data: msg_data }; + let enc_pub = PubKey { + x: uint256_from_decimal_string(&data.enc_pub_key[0]), + y: uint256_from_decimal_string(&data.enc_pub_key[1]), + }; + contract + .publish_message(&mut app, user2(), message, enc_pub) + .expect("PublishMessage must succeed"); + } + "processMessage" => { + let data: ProcessMessageData = deserialize_data(&entry.data); + + app.update_block(next_block_11_min); // End voting period + app.update_block(next_block); + contract + .start_process(&mut app, owner()) + .expect("StartProcessPeriod must succeed"); + + let new_state_commitment = + uint256_from_decimal_string(&data.new_state_commitment); + let proof = to_groth16_proof_type(&data.proof); + + contract + .process_message(&mut app, owner(), new_state_commitment, proof) + .expect("ProcessMessage with real proof must succeed"); + } + "processTally" => { + let data: ProcessTallyData = deserialize_data(&entry.data); + + contract + .stop_processing(&mut app, owner()) + .expect("StopProcessingPeriod must succeed"); + assert_eq!( + Period { + status: PeriodStatus::Tallying + }, + contract.get_period(&app).unwrap() + ); + + let new_tally_commitment = + uint256_from_decimal_string(&data.new_tally_commitment); + let proof = to_groth16_proof_type(&data.proof); + + contract + .process_tally(&mut app, owner(), new_tally_commitment, proof) + .expect("ProcessTally with real proof must succeed"); + } + "stopTallyingPeriod" => { + let data: StopTallyingPeriodData = deserialize_data(&entry.data); + + expected_results = data + .results + .iter() + .map(|v| uint256_from_decimal_string(v)) + .collect(); + let salt = uint256_from_decimal_string(&data.salt); + + app.update_block(next_block_11_min); + contract + .stop_tallying(&mut app, owner(), expected_results.clone(), salt) + .expect("StopTallyingPeriod with matching results/salt must succeed"); + + assert_eq!( + Period { + status: PeriodStatus::Ended + }, + contract.get_period(&app).unwrap() + ); + } + _ => {} + } + } + + assert!(!expected_results.is_empty(), "logs.json must contain a stopTallyingPeriod entry"); + + let expected_total: Uint256 = expected_results.iter().fold(Uint256::zero(), |acc, r| acc + *r); + assert_eq!( + contract.get_all_result(&app).unwrap(), + expected_total, + "on-chain tally total must match the results recorded in logs.json" + ); + } + // ── set_round_info permission tests ────────────────────────────────────── #[test] diff --git a/contracts/amaci/src/state.rs b/contracts/amaci/src/state.rs index da5de148..2532f74b 100644 --- a/contracts/amaci/src/state.rs +++ b/contracts/amaci/src/state.rs @@ -72,6 +72,8 @@ pub const VOICECREDITBALANCE: Map, Uint256> = Map::new("voice_credit_bal pub const NODES: Map, Uint256> = Map::new("nodes"); pub const MAX_VOTE_OPTIONS: Item = Item::new("max_vote_options"); +// Per-option vote weight cap enforced by the process circuit (0 = no limit) +pub const MAX_VOTES_PER_OPTION: Item = Item::new("max_votes_per_option"); pub const CURRENT_STATE_COMMITMENT: Item = Item::new("current_state_commitment"); pub const CURRENT_TALLY_COMMITMENT: Item = Item::new("current_tally_commitment"); diff --git a/contracts/amaci/src/test/amaci_test/logs.json b/contracts/amaci/src/test/amaci_test/logs.json index 187b44e5..8c9b9b87 100644 --- a/contracts/amaci/src/test/amaci_test/logs.json +++ b/contracts/amaci/src/test/amaci_test/logs.json @@ -25,20 +25,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "9946328582796284454609740485327123080675545257400313914438454878740655605850", - "11134756559979194073717200475729050254697225971004392388301744365347862336908", - "16987619435777674336898218776840505637095452726229335191056025236243630946581", - "5991882729708851880567462228315004364205866783456667587279451266903635267323", - "13425021051782091050905877797770870743002852633245905891799124606371720322288", - "16945326780825115105073800936363362280221712235502173843296584530142838453083", - "16557568778651178554684778825904303798408937857626710615132090036772360723154", - "9715564345550787970634675675957423822963310193959266031353864051134768301260", - "11822867353227434448674864705347123656944213974298231091092568975881266060251", - "17085857918367670505098877256696051658476481605489779616879586529396409360213" + "10199538548927120714932940033352720386974078405513490410706428349310392875182", + "13655872631808810427644409650428422335240746202781882618915838707176748177032", + "4522510631409687676287452827143364603161458319387795781089857236379245124620", + "12631360558122316932395977841092807384254788197434707521393446594481440406888", + "5064455035049685748075782645836256439144373654497265984503385954053756719991", + "4949918418208276018510186207756754181199761410148368199846220358869622265113", + "5133442886621740816906245138693327457584430710691836383349337725304320983752", + "21742787944525354780732770859294263180265728165218559055149235794885028481475", + "19422152523225351173772773148035207096795669433417888803696755744763175112484", + "10819561521219992066365168346219236906024782170984835580367633443988113374742" ], "encPubKey": [ - "18979331468098887881673699118194050570316533757514752527504868825075845789737", - "12011856559607995371355378432622901758415835168346079183419976119635175249657" + "8338997010971674380540897807518105678225073705648002510933270265809332194034", + "13954517998564222966059351125502869538349466448160605276291359530546041450223" ] } }, @@ -46,20 +46,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "12470203084818010829496697404393864067898743981956569923905283789155050097092", - "17349811068332292275436031666631255366358525218807009162068171959603055593386", - "8403911220388431688573886899395591975116156406896622405705650973980278354512", - "13743670957853509368804127109967350632796443643191998891769953064577408983573", - "2334973997658186696766301135603916837658566733238716776666306011457114257155", - "10413370890153289184358978451302324317416205786513480312648538359484141163495", - "16395905452776797556468910260535482053842538245059086981729727051317873165807", - "3147345343606943659963923269443452545482756158504817129093251345309056184892", - "19300260782025484529398577449416183846890138060839973308395755128280000343389", - "14893104591926176314212783227081521765104332507135636233406660233709721902625" + "21413339661421681364812790641898829049904718437636946307217227781082821973592", + "20866556127828344449917046633348352053125043790470431083597009723576339931172", + "8635053267067632405674900512529287999708821487476410722585604545612226454061", + "5695656229573187806439006959232123033670721187477559694603050772103462573924", + "12050486414260508422380213600501293647005530392590103757769436495303699792315", + "6109464031463685437699832946297413880643404513610789419211882541091402968519", + "13237072433322268487406531470690349764086173953414719991950588721660354999372", + "12030953900314540795016119474423496015821661692373799828494139055880859538321", + "20588181222708073166756414028925379895453337390525906764143801049941065230189", + "2806495032912144929978846495374342223921156224156462179036151703131574152213" ], "encPubKey": [ - "8079704687731372546907506015180380385492213695307277251991960705255513994434", - "4418248669674966905335204736163220610645370450361176046908192735759343701553" + "14790633911774005825263096161370523514919388824876132387568629307861038175119", + "12920696696847634835141935547586976377793376302885926386553774258531479916623" ] } }, @@ -67,9 +67,9 @@ "type": "proofDeactivate", "data": { "proof": { - "pi_a": "06efd69472c9d7ba6763a84a55e44680f0b6d3e76612e0d18e4b75d86e0b959e085afce90e0ae29e1f996d9e806148d0682f3241f56be72f24831bc7008de424", - "pi_b": "15bddb3dce5cbbe15882789d7ad7825b411c7566cb72acbc30ce5c1b21f09b6022aeae163066b944cd4b2402f924f64f0696a17604ba6a4e9a05a8de428b5dc015c428b6da15e44639c7a619c39faf15839c21c6e24d430c6d3c28d5773cab672c1fa3c99696676a0b2e7c76521d6ffb22d9d25695040bd4b92a6d467bb9cbff", - "pi_c": "2b978cea20e3a2b342f4c9f1dd20380345445c2d5538da0e991e936ddfa6cd1f000936ba28ee7a64ebfd1a00ff9f954ed9e7a67074aac4af2bb5b5ef25d4cfee" + "pi_a": "06ef627c054aa4c83452b8fa5d7fb84840b9640f729261c3b63c4ce3cea1037c1cd9cba65300a8ae45ff75d496c61dca09e6a5bccad88658d98d3dd7d066d851", + "pi_b": "068abb620a55a7f30929a57a33073ac4ec48079410b1907b495a68f6226d46ae1636511c5eb0d992bf73738dae4b1a5a5e35acb3b3cb4ca94699e4c77281bdb11460c9658ce22731754c24e002834879cd1fac35795036bccaa1cb0cc624d2c81169629d21bfedae1ccaf6a73caff2dfb9eda1ed28e740c94c58662d48643514", + "pi_c": "1f64bdfd5a9d89f5b9e8d07576545fdd86833de1b18d8352064f4a5d71c8f158125a99f2c645bdaf1e503d711c6a6430e5bd989acb794e16b611380cb30b9ab4" }, "size": "2", "newDeactivateCommitment": "16594648813117521549607651409199825676087230774332331178259600792935825001695", @@ -79,7 +79,7 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "1592144379998706346090659968263191628215225704483103412596180016620924969746", + "10641036700368614459615677103397157737551724537581240700605661156499962601134", "11130071843769412659933467398663901612334403299453766868287010509469499313889", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "9822028196133927497745238851722523433315624887764435741027677520879911614812", @@ -105,15 +105,15 @@ "20437799137966928537540131352831724208517012039281435330961519441894644714811" ], "proof": { - "pi_a": "0f61203de76d3b5ecf426197376dbe66bf1970a904ba3dc859e0043ee9bd60c814e9db093f8a81a69562bfcdca55fdf7f7fb416436ad281877dbf25689408067", - "pi_b": "19dd925f935cea82f743bc5dc734bd7708de52202984448654cedfc8314434761bee7e020133999c81023b037583b3cef3bccedb7981463d186e9c2df5d8d0a10e5e695a8aa9ae410077032e1e38c179d6101216c5bc89116225798a9e5d0772202d5e9c0be4d6d58ec3b35a1d6e02c6a26aea976edb4a12098de946b1d1924a", - "pi_c": "00a5f70002576cf484b26defc1662f1d2540af6429154d7380e2ea720d9b2eef01c3a0343ee6e51c4dc6bf64ab583a885bd64a0d216ca18802fa05c91806bb01" + "pi_a": "15d7628548f9c805ed969b15fa977108db741e15435d3e5942774a813d4b7b590d503f7210c274ffb5536eb6a10e0eeeca53341089e5f28457e4c37e31812c40", + "pi_b": "229b8fa828fbeae3b8984e87bbf2a1956d0aeaff6eb27b805f0c81f8414807a117294665f6af32083d17aba75078d8387c7ce3dd7e7f00247b0544c46f26a697163145e7b75b52ed6d3b9b52b3b8399345bd783b7ff7d7a45e248735b32b63fe2d6c752356728bb97eb531849cc8e894e8a2d930210d300a20cbd4184c9fae6d", + "pi_c": "28ae0a1c52f015dac0a6c2ab765b1ef0585b2a8b8e3198b3e1f2b0ffbcb80d4c0f19fa28289b657c14ddbf6e504ef431ca6cd7aa9f49297809ee09d462da5ee4" }, "d": [ - "17754022195504608025749518087537133637525831205766820796405743534618504862734", - "19819676171232462163631587566138303992104749363631315471805133936070914972879", - "3651680750510785366311203551458633473273736408707142562309616160422291955579", - "17554651075467677913973936191398252326339367941232214290968751099598007812103" + "10429275752581465043716743428927652264952855894921267050669121213403906525022", + "5229928821704293629422300883038551475821805973425538223807642872731614682747", + "12584624188331812056728058433134688487689081239749498128311790830626561180785", + "9554480257957972556963874295494677102261600637704276946797523829472465658661" ], "nullifier": "11275217544102381393112296424037264033603560840958598162766803219699297021995" }, @@ -121,30 +121,30 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "11275217544102381393112296424037264033603560840958598162766803219699297021995", - "17754022195504608025749518087537133637525831205766820796405743534618504862734", - "19819676171232462163631587566138303992104749363631315471805133936070914972879", - "3651680750510785366311203551458633473273736408707142562309616160422291955579", - "17554651075467677913973936191398252326339367941232214290968751099598007812103" + "10429275752581465043716743428927652264952855894921267050669121213403906525022", + "5229928821704293629422300883038551475821805973425538223807642872731614682747", + "12584624188331812056728058433134688487689081239749498128311790830626561180785", + "9554480257957972556963874295494677102261600637704276946797523829472465658661" ] }, { "type": "publishMessage", "data": { "message": [ - "4108506414071707876077764872754416884084069067830124606394622137225951228881", - "11758593284611531953761572449126297529615339382369007904876347611087867354585", - "10943560038229027475384844996338120310036530173920221702981340747683946223290", - "15144582931592231724667003491769446928150331804589629284514214786718880838051", - "1473251834473016546276351987473339587999863427209607406885769932469535558299", - "5165296687661288641362621457981500178798684849494574386450681097714726706752", - "13236460988625002930600200978449922471805226230677743380682867921920355266167", - "3060913565465157592283414139081365462032581528956477294583667076564041762274", - "1955500879023896598949479239210921667529214507887324681557978983873072450436", - "13212776588657180654528185950027472367308039232849008029541156031671285067398" + "1791680339236253889870974892742243504774453269866464278763091344014289183583", + "12912656003372824590342609694634798852678099940841567149859709770499934884335", + "18791018738860930723859857404737068756536348601057408596997912519625044543281", + "16584393316295443194801986221520890994492417484962308885046757915488186492538", + "10667420618487120661693041221680953120443615201158787705620484935765005559184", + "6083096472073668943522615658350531348879717470376415651153190268996804830829", + "7369335400032223970672086473473920997874197133330216122083652342087715654089", + "11076008935601220303260021284944519703873108079428411147338084895255352491011", + "12786284176937166464320672251025772023625536059394965982704532763666085546223", + "9007229654543442343208836150206963612011422402123778131650148326366616169094" ], "encPubKey": [ - "9159330977504123435105802117017613576238693018072399699796437975868150969255", - "14679692412897032802303712326340821606122389084116501273639958299755444547974" + "15475608500420978206129166766118247249151489996252896147336817370649335541072", + "17790489522381535934163155608043378122485307312462592830426988610875473620439" ] } }, @@ -152,20 +152,20 @@ "type": "publishMessage", "data": { "message": [ - "13850266323177485269276787242814919132533331431268363863397482142418925462033", - "2906422079885434851203252501337881452052779893347463248915370487902467809621", - "7646936645162456815847523562177925534185206184531941666352693606092464430468", - "7550039366721693178659583177886125574184765422908624170496753732755349454133", - "12832321729723491510612717720276685972689540442164132173319302262596528942729", - "7716581001704121079638254881475266443698421250050785848031387401170763646361", - "12064642044108665525947893047020322953012115442632704286508067651912034132028", - "15775713376603728849064505608455505736526089961571617395051811633060173565568", - "17563760991157186551571608327825078772459583060503937437401085038611447854551", - "2386977777156031543562981082837599295153592596476328729887490849837871888602" + "2934286026199833719272274363447804657603644797607191690960611904679092494208", + "12686659491981967937885141550488300901190472917973423890635403564395400536901", + "7822555136442100122666187117646855225846556970307757521210899898820044437020", + "17114049849715767097782437560582426322864545681879971490785412509629340536949", + "14807269430265246696328008798735566109518374105362787944453596069680861518670", + "19122159091541582051084901704653445387383915132506412226090839918177930525077", + "6534696491684083090835559331095394062070656382177143005801725078565336692891", + "9152087624780184790158276476573072241077492398510162683728830438363124733227", + "20660863482905804982381708023290238625536550513031385627760316105386421306574", + "15773470826016432067698852442561603741738010247964917243277038599536143508214" ], "encPubKey": [ - "17070855708645606066161375991312395920063787998405891631884602286435945949540", - "4316452228410096399774340359572816039382020188262894024298916241091268418765" + "3246882523858798579653725632245677815572520121562528893682828338364433544239", + "251469813163058146760472586440492200141935016615685184229967914227285567741" ] } }, @@ -173,20 +173,20 @@ "type": "publishMessage", "data": { "message": [ - "15583455409310584288360043618185883851307265743123633299292741128110974046233", - "9831116464754375249844868059902653007388962237904722566482472912518374777266", - "19235981827977373225840136796804989261219032164267865386527660933312656847937", - "13864823038688293434264068755544347037520921370954997381331801100763078952322", - "15459717997748975667071597472796368153750107065277868768217019027811828610194", - "3787096387771556733600964082154216211944530995426941037270036009580470405246", - "2145625068102965126469983758868994883972067014098655616533552960205558576018", - "17157154468388852829181167480354020023392614076890143625355981990871485716646", - "6143975903497574274301757917709638446697581998634984446336485220541315284247", - "5555337434014984541196177159529483995474574331484827332877898597232857611420" + "6040209671941422224396602067545041920520358782195834435128413473696786837333", + "19960515712904479693190879460799401141735713693858466758411443985892378422179", + "18684049546709024405268090451084859257331206297993892767152697777168105193950", + "4417067055532741121958645526962600415558295671361599386718254482151320751800", + "8831014646401085985422075959553401353474401368058172621332926526032482358682", + "19217537575108723326676749657287652803032945360366531731763213424659467783655", + "18251504118463383519769062943112898564880497948309370456680815597871817867538", + "2086572403656215063854110231912436577966018392734032815223971612619051390233", + "4272366053435368552491549023761060025938452467762466263138690546603872915203", + "8120048915061515603211575426724595332593895770922805744882866281921989790750" ], "encPubKey": [ - "21254950833075681162174257678461774798192781477237220269653245169739865412295", - "7709017943314571318424342092525223355111327868368330545889651918873729504233" + "19756256018645496875540731296733822049290414734956005295678189287448357913848", + "2707256377586192612467480538754151266138587489076506164860615112668134194308" ] } }, @@ -194,19 +194,19 @@ "type": "processMessage", "data": { "proof": { - "pi_a": "1d53f70883f7a1ee101402543602a765ed7be6d681fe97b9be2843ee3dfca39c1ea5dfa9913edd231cc66c86a3f7071d8a853e859e1524fb06cea3783225ec60", - "pi_b": "1d3a5dbc3af9f61f03fa16b2f0626d70ef2c0f1db06570ac4038e71d68f902bc085378822020cb5bd3f2ae56149bcd0e9724c21f869d6c506fca96f48b073a0f05ac6302c5f8a858fa55eb1536d8ef9aaca455384bc7e5984a76956469bf3f692810e271fcb8a5129bf1aad974dad4a5c131f98d36f880541833f345d214bc28", - "pi_c": "117d279a0c53fda61c4f3de52c7c79b4355876cf2da83b4de824ca98f35cb55a15d1b836924506ef18ada8ff554ea548a10a4deec94046a95a3291685d741510" + "pi_a": "2129ce4afbd1ef82ebfc1ab787c4347898badf204d996aff3774e6ad9c3bc0421f68466d74479415df9140b7e8dd10a3069eb4e164c90b28eb3b7bab5297d718", + "pi_b": "10030e86baf67dfa8fe66d6da6f4a5ba6b71b2ec4756a13b27dd6cb5ef9c1c651735599e35f6074a6b24c484ba7cc551f6d20f31297d52dfba49eb6d80b00e7006b424e0213d6e832fdd704937bcece614195390f55fbc19669ebe474709dbac0af047834f35a11bcfabead0e400338a17aa64fac9fa2c52e2d1bc917ef733ae", + "pi_c": "1e604286ffb13ff0b0bec30eb81e9829f02208e649e672cb8da38b134e672a282220a5ce7be897ff5f31ca6dc8f76b4ba7b0a86d5bd52a9584e79421d73853a7" }, - "newStateCommitment": "15845738180810735067389398627532955788873440251908695072415134434693413598962" + "newStateCommitment": "15747144277495644891688004720427985491197111452878407902812834851808276585502" }, "inputs": [ "18446744086594453509", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "7298956495550857662319854515785015411959560697873346667413148931812507020180", - "7411157069539872994419095533452009492232418703617663186521918534111524812705", - "15845738180810735067389398627532955788873440251908695072415134434693413598962", + "526044335307134503491815026254278366672136736885761787302017270911568883596", + "6346528390895127279807599986474483438865420111586097124828966882255208009484", + "15747144277495644891688004720427985491197111452878407902812834851808276585502", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "1" ] @@ -215,15 +215,15 @@ "type": "processTally", "data": { "proof": { - "pi_a": "00f20348f42415274cb4c7a0e8f03c9836e79903c409debb93c47ddcccba5a65256b1fb5b442311b1c465d481076e1d2645599fd731ba50799e857f28b08e162", - "pi_b": "261e10b8e1c81e5a4623c262903089734fde9e4fa64cb2cb9928e3fe011240c6265f4fc6ba1e380d1d13cf380716dc6a305ab1263d3889055f9d063f1120569a085f6935f7572fb256f4ee4c5a4a74a2d5e03d4e3572735d27624ee9ed4483791301f5fb0bc6ee933374388a8241776b1ec4b9b7ac50e9531e9842c8a91cc9f7", - "pi_c": "0ba2b1978304df6570a5e3640b37b6f4e9f52b1d39a80d3b43818d19b86b7da4198712dfd5a75784d190d6b53f3d1aaef396aef69fe09f4341037f06632ced49" + "pi_a": "1d4d31970050c6dd47346215fa67a04a8b0b171539ba662d1e6643a4a116aef22289120a6384615ad650d8482223f6925f18311d82aecf58acfaff3a252f1c02", + "pi_b": "1dda84bf5bef508fde174efefe91723c9fa37c37b1a9719f4ccff9272125facd2f26e1cbb10fa46afdc770e12687630b9b56234e94967a61ba2d70ddc76bf37f21de8517756f16fe243ec4ca1b63ef999f5e59e25c76b6ce275197b970581f7227ccbcb1352195eda09fb8322fdbc313660459dd0be0c4c92982f875fd0c445a", + "pi_c": "2bbfa115c59f51affef995e5d3bdc2d317c576c5e1b60bfc092b807926f827c9078076b42e48c997dc9c308a26bcd01136b55584688d951e0ae77e1afaa0ba83" }, "newTallyCommitment": "5119554139732678588072159140519209785192441754076468540607385260141479782116" }, "inputs": [ "12884901888", - "15845738180810735067389398627532955788873440251908695072415134434693413598962", + "15747144277495644891688004720427985491197111452878407902812834851808276585502", "0", "5119554139732678588072159140519209785192441754076468540607385260141479782116" ] @@ -231,8 +231,14 @@ { "type": "stopTallyingPeriod", "data": { - "results": ["0", "0", "6000000000000000000000036", "0", "0"], + "results": [ + "0", + "0", + "6000000000000000000000036", + "0", + "0" + ], "salt": "20042" } } -] +] \ No newline at end of file diff --git a/contracts/api-saas/src/contract.rs b/contracts/api-saas/src/contract.rs index 9d2d729f..91719606 100644 --- a/contracts/api-saas/src/contract.rs +++ b/contracts/api-saas/src/contract.rs @@ -126,6 +126,7 @@ pub fn execute( deactivate_enabled, voice_credit_mode, registration_mode, + max_votes_per_option, } => execute_create_amaci_round( deps, env, @@ -139,6 +140,7 @@ pub fn execute( deactivate_enabled, voice_credit_mode, registration_mode, + max_votes_per_option, ), ExecuteMsg::UpdateFeeConfig { config } => execute_update_fee_config(deps, info, config), ExecuteMsg::SignUp { @@ -805,6 +807,7 @@ pub fn execute_create_amaci_round( deactivate_enabled: bool, voice_credit_mode: VoiceCreditMode, registration_mode: RegistrationModeConfig, + max_votes_per_option: Option, ) -> Result { // Only operators can create AMACI rounds via registry if !OPERATORS.has(deps.storage, &info.sender) { @@ -844,6 +847,7 @@ pub fn execute_create_amaci_round( deactivate_enabled, voice_credit_mode: voice_credit_mode.clone(), registration_mode, + max_votes_per_option, }; // Execute the contract call to registry with the required fee from SaaS balance diff --git a/contracts/api-saas/src/msg.rs b/contracts/api-saas/src/msg.rs index 5c81ba35..e73bdbc1 100644 --- a/contracts/api-saas/src/msg.rs +++ b/contracts/api-saas/src/msg.rs @@ -86,6 +86,10 @@ pub enum ExecuteMsg { // Registration Mode: combined access control and state initialization registration_mode: RegistrationModeConfig, + + // Per-option vote weight cap (None or 0 = no limit, must fit in 32 bits) + #[serde(default)] + max_votes_per_option: Option, }, // Update local fee config mirror (admin only) diff --git a/contracts/api-saas/src/multitest/mod.rs b/contracts/api-saas/src/multitest/mod.rs index 2646b182..8b56fcbc 100644 --- a/contracts/api-saas/src/multitest/mod.rs +++ b/contracts/api-saas/src/multitest/mod.rs @@ -241,6 +241,7 @@ impl SaasContract { deactivate_enabled, voice_credit_mode, registration_mode, + max_votes_per_option: None, }, funds, ) diff --git a/contracts/registry/src/contract.rs b/contracts/registry/src/contract.rs index ea9f2c29..84235931 100644 --- a/contracts/registry/src/contract.rs +++ b/contracts/registry/src/contract.rs @@ -105,6 +105,7 @@ pub fn execute( deactivate_enabled, voice_credit_mode, registration_mode, + max_votes_per_option, } => execute_create_round( deps, env, @@ -118,6 +119,7 @@ pub fn execute( deactivate_enabled, voice_credit_mode, registration_mode, + max_votes_per_option, ), ExecuteMsg::SetValidators { addresses } => { execute_set_validators(deps, env, info, addresses) @@ -173,6 +175,7 @@ pub fn execute_create_round( deactivate_enabled: bool, voice_credit_mode: cw_amaci::state::VoiceCreditMode, registration_mode: cw_amaci::msg::RegistrationModeConfig, + max_votes_per_option: Option, ) -> Result { validate_dora_address(operator.as_str())?; @@ -227,6 +230,7 @@ pub fn execute_create_round( vote_option_map, round_info, voting_time, + max_votes_per_option, circuit_type, certification_system, poll_id, diff --git a/contracts/registry/src/msg.rs b/contracts/registry/src/msg.rs index ae3bbc33..cb9d04d0 100644 --- a/contracts/registry/src/msg.rs +++ b/contracts/registry/src/msg.rs @@ -52,6 +52,10 @@ pub enum ExecuteMsg { // Registration Mode: combined access control and state initialization registration_mode: RegistrationModeConfig, + + // Per-option vote weight cap (None or 0 = no limit, must fit in 32 bits) + #[serde(default)] + max_votes_per_option: Option, }, SetValidators { addresses: ValidatorSet, diff --git a/contracts/registry/src/multitest/mod.rs b/contracts/registry/src/multitest/mod.rs index 693d9539..cecb2b37 100644 --- a/contracts/registry/src/multitest/mod.rs +++ b/contracts/registry/src/multitest/mod.rs @@ -212,6 +212,7 @@ impl AmaciRegistryContract { users: vec![], // Empty whitelist for open registration }, }, + max_votes_per_option: None, }; app.execute_contract(sender, self.addr(), &msg, send_funds) @@ -276,6 +277,7 @@ impl AmaciRegistryContract { registration_mode: cw_amaci::msg::RegistrationModeConfig::SignUpWithStaticWhitelist { whitelist, }, + max_votes_per_option: None, }; app.execute_contract(sender, self.addr(), &msg, send_funds) @@ -340,6 +342,7 @@ impl AmaciRegistryContract { registration_mode: cw_amaci::msg::RegistrationModeConfig::SignUpWithStaticWhitelist { whitelist, }, + max_votes_per_option: None, }; app.execute_contract(sender, self.addr(), &msg, send_funds) @@ -388,6 +391,7 @@ impl AmaciRegistryContract { registration_mode: cw_amaci::msg::RegistrationModeConfig::SignUpWithOracle { oracle_pubkey: oracle_whitelist_pubkey, }, + max_votes_per_option: None, }; app.execute_contract(sender, self.addr(), &msg, send_funds) @@ -438,6 +442,7 @@ impl AmaciRegistryContract { pre_deactivate_root, pre_deactivate_coordinator, }, + max_votes_per_option: None, }; app.execute_contract(sender, self.addr(), &msg, send_funds) @@ -487,6 +492,7 @@ impl AmaciRegistryContract { amount: Uint256::from_u128(100u128), }, registration_mode: RegistrationModeConfig::SignUpWithStaticWhitelist { whitelist }, + max_votes_per_option: None, }; app.execute_contract(sender, self.addr(), &msg, send_funds) diff --git a/contracts/registry/src/test/amaci_test/logs.json b/contracts/registry/src/test/amaci_test/logs.json index 187b44e5..8c9b9b87 100644 --- a/contracts/registry/src/test/amaci_test/logs.json +++ b/contracts/registry/src/test/amaci_test/logs.json @@ -25,20 +25,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "9946328582796284454609740485327123080675545257400313914438454878740655605850", - "11134756559979194073717200475729050254697225971004392388301744365347862336908", - "16987619435777674336898218776840505637095452726229335191056025236243630946581", - "5991882729708851880567462228315004364205866783456667587279451266903635267323", - "13425021051782091050905877797770870743002852633245905891799124606371720322288", - "16945326780825115105073800936363362280221712235502173843296584530142838453083", - "16557568778651178554684778825904303798408937857626710615132090036772360723154", - "9715564345550787970634675675957423822963310193959266031353864051134768301260", - "11822867353227434448674864705347123656944213974298231091092568975881266060251", - "17085857918367670505098877256696051658476481605489779616879586529396409360213" + "10199538548927120714932940033352720386974078405513490410706428349310392875182", + "13655872631808810427644409650428422335240746202781882618915838707176748177032", + "4522510631409687676287452827143364603161458319387795781089857236379245124620", + "12631360558122316932395977841092807384254788197434707521393446594481440406888", + "5064455035049685748075782645836256439144373654497265984503385954053756719991", + "4949918418208276018510186207756754181199761410148368199846220358869622265113", + "5133442886621740816906245138693327457584430710691836383349337725304320983752", + "21742787944525354780732770859294263180265728165218559055149235794885028481475", + "19422152523225351173772773148035207096795669433417888803696755744763175112484", + "10819561521219992066365168346219236906024782170984835580367633443988113374742" ], "encPubKey": [ - "18979331468098887881673699118194050570316533757514752527504868825075845789737", - "12011856559607995371355378432622901758415835168346079183419976119635175249657" + "8338997010971674380540897807518105678225073705648002510933270265809332194034", + "13954517998564222966059351125502869538349466448160605276291359530546041450223" ] } }, @@ -46,20 +46,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "12470203084818010829496697404393864067898743981956569923905283789155050097092", - "17349811068332292275436031666631255366358525218807009162068171959603055593386", - "8403911220388431688573886899395591975116156406896622405705650973980278354512", - "13743670957853509368804127109967350632796443643191998891769953064577408983573", - "2334973997658186696766301135603916837658566733238716776666306011457114257155", - "10413370890153289184358978451302324317416205786513480312648538359484141163495", - "16395905452776797556468910260535482053842538245059086981729727051317873165807", - "3147345343606943659963923269443452545482756158504817129093251345309056184892", - "19300260782025484529398577449416183846890138060839973308395755128280000343389", - "14893104591926176314212783227081521765104332507135636233406660233709721902625" + "21413339661421681364812790641898829049904718437636946307217227781082821973592", + "20866556127828344449917046633348352053125043790470431083597009723576339931172", + "8635053267067632405674900512529287999708821487476410722585604545612226454061", + "5695656229573187806439006959232123033670721187477559694603050772103462573924", + "12050486414260508422380213600501293647005530392590103757769436495303699792315", + "6109464031463685437699832946297413880643404513610789419211882541091402968519", + "13237072433322268487406531470690349764086173953414719991950588721660354999372", + "12030953900314540795016119474423496015821661692373799828494139055880859538321", + "20588181222708073166756414028925379895453337390525906764143801049941065230189", + "2806495032912144929978846495374342223921156224156462179036151703131574152213" ], "encPubKey": [ - "8079704687731372546907506015180380385492213695307277251991960705255513994434", - "4418248669674966905335204736163220610645370450361176046908192735759343701553" + "14790633911774005825263096161370523514919388824876132387568629307861038175119", + "12920696696847634835141935547586976377793376302885926386553774258531479916623" ] } }, @@ -67,9 +67,9 @@ "type": "proofDeactivate", "data": { "proof": { - "pi_a": "06efd69472c9d7ba6763a84a55e44680f0b6d3e76612e0d18e4b75d86e0b959e085afce90e0ae29e1f996d9e806148d0682f3241f56be72f24831bc7008de424", - "pi_b": "15bddb3dce5cbbe15882789d7ad7825b411c7566cb72acbc30ce5c1b21f09b6022aeae163066b944cd4b2402f924f64f0696a17604ba6a4e9a05a8de428b5dc015c428b6da15e44639c7a619c39faf15839c21c6e24d430c6d3c28d5773cab672c1fa3c99696676a0b2e7c76521d6ffb22d9d25695040bd4b92a6d467bb9cbff", - "pi_c": "2b978cea20e3a2b342f4c9f1dd20380345445c2d5538da0e991e936ddfa6cd1f000936ba28ee7a64ebfd1a00ff9f954ed9e7a67074aac4af2bb5b5ef25d4cfee" + "pi_a": "06ef627c054aa4c83452b8fa5d7fb84840b9640f729261c3b63c4ce3cea1037c1cd9cba65300a8ae45ff75d496c61dca09e6a5bccad88658d98d3dd7d066d851", + "pi_b": "068abb620a55a7f30929a57a33073ac4ec48079410b1907b495a68f6226d46ae1636511c5eb0d992bf73738dae4b1a5a5e35acb3b3cb4ca94699e4c77281bdb11460c9658ce22731754c24e002834879cd1fac35795036bccaa1cb0cc624d2c81169629d21bfedae1ccaf6a73caff2dfb9eda1ed28e740c94c58662d48643514", + "pi_c": "1f64bdfd5a9d89f5b9e8d07576545fdd86833de1b18d8352064f4a5d71c8f158125a99f2c645bdaf1e503d711c6a6430e5bd989acb794e16b611380cb30b9ab4" }, "size": "2", "newDeactivateCommitment": "16594648813117521549607651409199825676087230774332331178259600792935825001695", @@ -79,7 +79,7 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "1592144379998706346090659968263191628215225704483103412596180016620924969746", + "10641036700368614459615677103397157737551724537581240700605661156499962601134", "11130071843769412659933467398663901612334403299453766868287010509469499313889", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "9822028196133927497745238851722523433315624887764435741027677520879911614812", @@ -105,15 +105,15 @@ "20437799137966928537540131352831724208517012039281435330961519441894644714811" ], "proof": { - "pi_a": "0f61203de76d3b5ecf426197376dbe66bf1970a904ba3dc859e0043ee9bd60c814e9db093f8a81a69562bfcdca55fdf7f7fb416436ad281877dbf25689408067", - "pi_b": "19dd925f935cea82f743bc5dc734bd7708de52202984448654cedfc8314434761bee7e020133999c81023b037583b3cef3bccedb7981463d186e9c2df5d8d0a10e5e695a8aa9ae410077032e1e38c179d6101216c5bc89116225798a9e5d0772202d5e9c0be4d6d58ec3b35a1d6e02c6a26aea976edb4a12098de946b1d1924a", - "pi_c": "00a5f70002576cf484b26defc1662f1d2540af6429154d7380e2ea720d9b2eef01c3a0343ee6e51c4dc6bf64ab583a885bd64a0d216ca18802fa05c91806bb01" + "pi_a": "15d7628548f9c805ed969b15fa977108db741e15435d3e5942774a813d4b7b590d503f7210c274ffb5536eb6a10e0eeeca53341089e5f28457e4c37e31812c40", + "pi_b": "229b8fa828fbeae3b8984e87bbf2a1956d0aeaff6eb27b805f0c81f8414807a117294665f6af32083d17aba75078d8387c7ce3dd7e7f00247b0544c46f26a697163145e7b75b52ed6d3b9b52b3b8399345bd783b7ff7d7a45e248735b32b63fe2d6c752356728bb97eb531849cc8e894e8a2d930210d300a20cbd4184c9fae6d", + "pi_c": "28ae0a1c52f015dac0a6c2ab765b1ef0585b2a8b8e3198b3e1f2b0ffbcb80d4c0f19fa28289b657c14ddbf6e504ef431ca6cd7aa9f49297809ee09d462da5ee4" }, "d": [ - "17754022195504608025749518087537133637525831205766820796405743534618504862734", - "19819676171232462163631587566138303992104749363631315471805133936070914972879", - "3651680750510785366311203551458633473273736408707142562309616160422291955579", - "17554651075467677913973936191398252326339367941232214290968751099598007812103" + "10429275752581465043716743428927652264952855894921267050669121213403906525022", + "5229928821704293629422300883038551475821805973425538223807642872731614682747", + "12584624188331812056728058433134688487689081239749498128311790830626561180785", + "9554480257957972556963874295494677102261600637704276946797523829472465658661" ], "nullifier": "11275217544102381393112296424037264033603560840958598162766803219699297021995" }, @@ -121,30 +121,30 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "11275217544102381393112296424037264033603560840958598162766803219699297021995", - "17754022195504608025749518087537133637525831205766820796405743534618504862734", - "19819676171232462163631587566138303992104749363631315471805133936070914972879", - "3651680750510785366311203551458633473273736408707142562309616160422291955579", - "17554651075467677913973936191398252326339367941232214290968751099598007812103" + "10429275752581465043716743428927652264952855894921267050669121213403906525022", + "5229928821704293629422300883038551475821805973425538223807642872731614682747", + "12584624188331812056728058433134688487689081239749498128311790830626561180785", + "9554480257957972556963874295494677102261600637704276946797523829472465658661" ] }, { "type": "publishMessage", "data": { "message": [ - "4108506414071707876077764872754416884084069067830124606394622137225951228881", - "11758593284611531953761572449126297529615339382369007904876347611087867354585", - "10943560038229027475384844996338120310036530173920221702981340747683946223290", - "15144582931592231724667003491769446928150331804589629284514214786718880838051", - "1473251834473016546276351987473339587999863427209607406885769932469535558299", - "5165296687661288641362621457981500178798684849494574386450681097714726706752", - "13236460988625002930600200978449922471805226230677743380682867921920355266167", - "3060913565465157592283414139081365462032581528956477294583667076564041762274", - "1955500879023896598949479239210921667529214507887324681557978983873072450436", - "13212776588657180654528185950027472367308039232849008029541156031671285067398" + "1791680339236253889870974892742243504774453269866464278763091344014289183583", + "12912656003372824590342609694634798852678099940841567149859709770499934884335", + "18791018738860930723859857404737068756536348601057408596997912519625044543281", + "16584393316295443194801986221520890994492417484962308885046757915488186492538", + "10667420618487120661693041221680953120443615201158787705620484935765005559184", + "6083096472073668943522615658350531348879717470376415651153190268996804830829", + "7369335400032223970672086473473920997874197133330216122083652342087715654089", + "11076008935601220303260021284944519703873108079428411147338084895255352491011", + "12786284176937166464320672251025772023625536059394965982704532763666085546223", + "9007229654543442343208836150206963612011422402123778131650148326366616169094" ], "encPubKey": [ - "9159330977504123435105802117017613576238693018072399699796437975868150969255", - "14679692412897032802303712326340821606122389084116501273639958299755444547974" + "15475608500420978206129166766118247249151489996252896147336817370649335541072", + "17790489522381535934163155608043378122485307312462592830426988610875473620439" ] } }, @@ -152,20 +152,20 @@ "type": "publishMessage", "data": { "message": [ - "13850266323177485269276787242814919132533331431268363863397482142418925462033", - "2906422079885434851203252501337881452052779893347463248915370487902467809621", - "7646936645162456815847523562177925534185206184531941666352693606092464430468", - "7550039366721693178659583177886125574184765422908624170496753732755349454133", - "12832321729723491510612717720276685972689540442164132173319302262596528942729", - "7716581001704121079638254881475266443698421250050785848031387401170763646361", - "12064642044108665525947893047020322953012115442632704286508067651912034132028", - "15775713376603728849064505608455505736526089961571617395051811633060173565568", - "17563760991157186551571608327825078772459583060503937437401085038611447854551", - "2386977777156031543562981082837599295153592596476328729887490849837871888602" + "2934286026199833719272274363447804657603644797607191690960611904679092494208", + "12686659491981967937885141550488300901190472917973423890635403564395400536901", + "7822555136442100122666187117646855225846556970307757521210899898820044437020", + "17114049849715767097782437560582426322864545681879971490785412509629340536949", + "14807269430265246696328008798735566109518374105362787944453596069680861518670", + "19122159091541582051084901704653445387383915132506412226090839918177930525077", + "6534696491684083090835559331095394062070656382177143005801725078565336692891", + "9152087624780184790158276476573072241077492398510162683728830438363124733227", + "20660863482905804982381708023290238625536550513031385627760316105386421306574", + "15773470826016432067698852442561603741738010247964917243277038599536143508214" ], "encPubKey": [ - "17070855708645606066161375991312395920063787998405891631884602286435945949540", - "4316452228410096399774340359572816039382020188262894024298916241091268418765" + "3246882523858798579653725632245677815572520121562528893682828338364433544239", + "251469813163058146760472586440492200141935016615685184229967914227285567741" ] } }, @@ -173,20 +173,20 @@ "type": "publishMessage", "data": { "message": [ - "15583455409310584288360043618185883851307265743123633299292741128110974046233", - "9831116464754375249844868059902653007388962237904722566482472912518374777266", - "19235981827977373225840136796804989261219032164267865386527660933312656847937", - "13864823038688293434264068755544347037520921370954997381331801100763078952322", - "15459717997748975667071597472796368153750107065277868768217019027811828610194", - "3787096387771556733600964082154216211944530995426941037270036009580470405246", - "2145625068102965126469983758868994883972067014098655616533552960205558576018", - "17157154468388852829181167480354020023392614076890143625355981990871485716646", - "6143975903497574274301757917709638446697581998634984446336485220541315284247", - "5555337434014984541196177159529483995474574331484827332877898597232857611420" + "6040209671941422224396602067545041920520358782195834435128413473696786837333", + "19960515712904479693190879460799401141735713693858466758411443985892378422179", + "18684049546709024405268090451084859257331206297993892767152697777168105193950", + "4417067055532741121958645526962600415558295671361599386718254482151320751800", + "8831014646401085985422075959553401353474401368058172621332926526032482358682", + "19217537575108723326676749657287652803032945360366531731763213424659467783655", + "18251504118463383519769062943112898564880497948309370456680815597871817867538", + "2086572403656215063854110231912436577966018392734032815223971612619051390233", + "4272366053435368552491549023761060025938452467762466263138690546603872915203", + "8120048915061515603211575426724595332593895770922805744882866281921989790750" ], "encPubKey": [ - "21254950833075681162174257678461774798192781477237220269653245169739865412295", - "7709017943314571318424342092525223355111327868368330545889651918873729504233" + "19756256018645496875540731296733822049290414734956005295678189287448357913848", + "2707256377586192612467480538754151266138587489076506164860615112668134194308" ] } }, @@ -194,19 +194,19 @@ "type": "processMessage", "data": { "proof": { - "pi_a": "1d53f70883f7a1ee101402543602a765ed7be6d681fe97b9be2843ee3dfca39c1ea5dfa9913edd231cc66c86a3f7071d8a853e859e1524fb06cea3783225ec60", - "pi_b": "1d3a5dbc3af9f61f03fa16b2f0626d70ef2c0f1db06570ac4038e71d68f902bc085378822020cb5bd3f2ae56149bcd0e9724c21f869d6c506fca96f48b073a0f05ac6302c5f8a858fa55eb1536d8ef9aaca455384bc7e5984a76956469bf3f692810e271fcb8a5129bf1aad974dad4a5c131f98d36f880541833f345d214bc28", - "pi_c": "117d279a0c53fda61c4f3de52c7c79b4355876cf2da83b4de824ca98f35cb55a15d1b836924506ef18ada8ff554ea548a10a4deec94046a95a3291685d741510" + "pi_a": "2129ce4afbd1ef82ebfc1ab787c4347898badf204d996aff3774e6ad9c3bc0421f68466d74479415df9140b7e8dd10a3069eb4e164c90b28eb3b7bab5297d718", + "pi_b": "10030e86baf67dfa8fe66d6da6f4a5ba6b71b2ec4756a13b27dd6cb5ef9c1c651735599e35f6074a6b24c484ba7cc551f6d20f31297d52dfba49eb6d80b00e7006b424e0213d6e832fdd704937bcece614195390f55fbc19669ebe474709dbac0af047834f35a11bcfabead0e400338a17aa64fac9fa2c52e2d1bc917ef733ae", + "pi_c": "1e604286ffb13ff0b0bec30eb81e9829f02208e649e672cb8da38b134e672a282220a5ce7be897ff5f31ca6dc8f76b4ba7b0a86d5bd52a9584e79421d73853a7" }, - "newStateCommitment": "15845738180810735067389398627532955788873440251908695072415134434693413598962" + "newStateCommitment": "15747144277495644891688004720427985491197111452878407902812834851808276585502" }, "inputs": [ "18446744086594453509", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "7298956495550857662319854515785015411959560697873346667413148931812507020180", - "7411157069539872994419095533452009492232418703617663186521918534111524812705", - "15845738180810735067389398627532955788873440251908695072415134434693413598962", + "526044335307134503491815026254278366672136736885761787302017270911568883596", + "6346528390895127279807599986474483438865420111586097124828966882255208009484", + "15747144277495644891688004720427985491197111452878407902812834851808276585502", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "1" ] @@ -215,15 +215,15 @@ "type": "processTally", "data": { "proof": { - "pi_a": "00f20348f42415274cb4c7a0e8f03c9836e79903c409debb93c47ddcccba5a65256b1fb5b442311b1c465d481076e1d2645599fd731ba50799e857f28b08e162", - "pi_b": "261e10b8e1c81e5a4623c262903089734fde9e4fa64cb2cb9928e3fe011240c6265f4fc6ba1e380d1d13cf380716dc6a305ab1263d3889055f9d063f1120569a085f6935f7572fb256f4ee4c5a4a74a2d5e03d4e3572735d27624ee9ed4483791301f5fb0bc6ee933374388a8241776b1ec4b9b7ac50e9531e9842c8a91cc9f7", - "pi_c": "0ba2b1978304df6570a5e3640b37b6f4e9f52b1d39a80d3b43818d19b86b7da4198712dfd5a75784d190d6b53f3d1aaef396aef69fe09f4341037f06632ced49" + "pi_a": "1d4d31970050c6dd47346215fa67a04a8b0b171539ba662d1e6643a4a116aef22289120a6384615ad650d8482223f6925f18311d82aecf58acfaff3a252f1c02", + "pi_b": "1dda84bf5bef508fde174efefe91723c9fa37c37b1a9719f4ccff9272125facd2f26e1cbb10fa46afdc770e12687630b9b56234e94967a61ba2d70ddc76bf37f21de8517756f16fe243ec4ca1b63ef999f5e59e25c76b6ce275197b970581f7227ccbcb1352195eda09fb8322fdbc313660459dd0be0c4c92982f875fd0c445a", + "pi_c": "2bbfa115c59f51affef995e5d3bdc2d317c576c5e1b60bfc092b807926f827c9078076b42e48c997dc9c308a26bcd01136b55584688d951e0ae77e1afaa0ba83" }, "newTallyCommitment": "5119554139732678588072159140519209785192441754076468540607385260141479782116" }, "inputs": [ "12884901888", - "15845738180810735067389398627532955788873440251908695072415134434693413598962", + "15747144277495644891688004720427985491197111452878407902812834851808276585502", "0", "5119554139732678588072159140519209785192441754076468540607385260141479782116" ] @@ -231,8 +231,14 @@ { "type": "stopTallyingPeriod", "data": { - "results": ["0", "0", "6000000000000000000000036", "0", "0"], + "results": [ + "0", + "0", + "6000000000000000000000036", + "0", + "0" + ], "salt": "20042" } } -] +] \ No newline at end of file diff --git a/e2e/circuits/vkeys-amaci-2-1-1-5.json b/e2e/circuits/vkeys-amaci-2-1-1-5.json index a076d766..8fd3cfde 100644 --- a/e2e/circuits/vkeys-amaci-2-1-1-5.json +++ b/e2e/circuits/vkeys-amaci-2-1-1-5.json @@ -13,15 +13,15 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x14fcf460ec67f39e7604ce59622a530797f70d5dce2cdbfcc6285acb11a091490a51cc6cc5aec73e4b1fcd45f152e8d18d9831efa2ca2d8aba5ec00a5258a86c2588c3053fe7907bd6e3b3b455283a441df9f5e9cc8b1aca6712d37004c28e4311915d144397caf4c4e74e150159574574d84d4a620cc22e1ee695b45f0c09fb", - "vk_ic0": "0x152b83fbeccaaf60ff7c47ebcefc9368d1d81271fc47d36e3032f589112849c900ce96219b641b39a390c8fe58b8ff805e21e55257e1437c26285d030fb52a70", - "vk_ic1": "0x0722c7bc6aaf03f86fc32096b9ad50fa14a99d113cd02d3a26df629703f7b9b61a19f057b25b77efefe232bb2cc87d9637bca988fc0325bd8c9e4b1febe5eca4" + "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "vk_ic0": "0x2109d20e2dfb65b2564cdd873f95f21a9215d9757c6ec62637b8d80373e1e9bb066ef0037b411d062439a5034b5c71bcdc2df0e3999fe5b7afd7cb88a32ceb30", + "vk_ic1": "0x05199f9ffa6b1ec953808a3dd750ad9168ae7a1464ddcead6cf31d61530e22a215b34e716a4871c189f25cf43ebc656d3256812cb98179183df2a9da65da34b9" }, "tally_vkey": { "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x21770a545c0aaa828d45a00c7335a689ac65650edb60d582ae66928eb860ac8811ec3ee19549dc6bf84515db12f782b7c6848fe4d004d32a5d27bce19440c34a173c6f347154f90a6052e1ca1faf89d4940527f248597c340c5c6cdf436225342c0fa0a92e84c22bb553aa427aa53c0f5f3ba7f7d223f6eb89b7d7cba26eb070", + "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", "vk_ic0": "0x0b20a7584a8679cc6cf8e8cffc41ce9ad79c2cd0086214c3cb1af12146916bb9185b916c9938601b30c6fc4e7f2e1f1a7a94cb81e1774cb1f67b54eb33477e82", "vk_ic1": "0x081919adecf04dd5e1c31a3e34f8907d2ca613df81f99b3aa56c5027cd6416c201ddf039c717b1d29ecc2381db6104506731132f624e60cc09675a100028de25" }, @@ -29,7 +29,7 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x0b2b685a254c97378d11100e45db341efebcc5e3d026fe920fdf1cac04c5feb4135b02f250b191e658c55341d45184bde62cec70444c4f210fdb507d5622dc821fe7bc3e41c31a4e6b7288ca0d519b80b18e722712d24f8786155d683f0bff7101e736bd668785e26ceb252106aaa784c922e2509d37444c711da6b3d8d0c8ad", + "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", "vk_ic0": "0x141ed95aed8eac95334e6dbaa513736949402fd820920d8e2179d7be54593f60070ffd76988c62dbf2cf4a365da0fbecde7e7ccb39f1e0e0728a6941da3435cd", "vk_ic1": "0x2c1289b05f9093a1d4c7536093702b08d57654fae20ae871de2598565c43c8611d5bc6caad360c2b6f68480aa71efbcc506524104152bb73f79d9cb0f3d12180" }, @@ -37,8 +37,8 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x2b135a96b33686a78339372bd40e3bef10aea0554c15a4770aeecdea0ce74b65265875823bf58d64d42fdf4ab9b8dba0a8b71dc2c1a140c68069d013a661c6a4150290c14390c9f212516d006b2b67012db77104bb20f3b980e924069a27c725119f442673a5ead331dfdfbbb1963ff41eca2f0a518e535f7b6b44cea1efd3df", + "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", "vk_ic0": "0x29639aea06acd9b07e36d2456153d4e81581d65efb2fc93f0d54618398be1c471f49496bce6f344badecd9493d07faaaa2d09c7216734488f3ce2e2d0bd25be9", "vk_ic1": "0x20ccb32cbbbb10099ab8ef2bfd196ec22b3c07c8c7eba7076bb8d16be4aa69ad0b0ff4e2a298219ef216024cd65a8b26470a7daa2e8ce55af41038a74d5d589f" } -} \ No newline at end of file +} diff --git a/packages/circuits/circom/amaci/power/messageValidator.circom b/packages/circuits/circom/amaci/power/messageValidator.circom index 4e80edc1..8f3977a4 100644 --- a/packages/circuits/circom/amaci/power/messageValidator.circom +++ b/packages/circuits/circom/amaci/power/messageValidator.circom @@ -2,6 +2,7 @@ pragma circom 2.0.0; include "../../utils/verifySignature.circom"; include "../../../node_modules/circomlib/circuits/comparators.circom"; +include "../../../node_modules/circomlib/circuits/mux1.circom"; template MessageValidator() { // a) Whether the state leaf index is valid @@ -66,6 +67,10 @@ template MessageValidator() { signal input currentVotesForOption; signal input voteWeight; + // g) Per-option vote weight cap. 0 is a sentinel meaning "no limit" + // (a cap of 0 would forbid all votes, so 0 is safe to repurpose). + signal input maxVotesPerOption; + signal output newBalance; // Check that voteWeight is < sqrt(field size), so voteWeight ^ 2 will not @@ -91,8 +96,22 @@ template MessageValidator() { newBalance <== currentVoiceCreditBalance + currentCostsForOption.out - cost.out; + // Per-option cap check: valid when maxVotesPerOption == 0 (unlimited) + // or voteWeight <= maxVotesPerOption. Bit width 252 matches + // validVoteWeight above, since voteWeight may be up to ~2^127. + component capUnlimited = IsZero(); + capUnlimited.in <== maxVotesPerOption; + + component withinCap = LessEqThan(252); + withinCap.in[0] <== voteWeight; + withinCap.in[1] <== maxVotesPerOption; + + // OR(capUnlimited, withinCap); both signals are boolean + signal validVotesPerOption; + validVotesPerOption <== capUnlimited.out + withinCap.out - capUnlimited.out * withinCap.out; + component validUpdate = IsEqual(); - validUpdate.in[0] <== 7; + validUpdate.in[0] <== 8; validUpdate.in[1] <== validSignature.valid + sufficientVoiceCredits.out + validVoteWeight.out + @@ -100,7 +119,8 @@ template MessageValidator() { validStateLeafIndex.out + // validTimestamp.out + validVoteOptionIndex.out + - validPollId.out; + validPollId.out + + validVotesPerOption; signal output isValid; isValid <== validUpdate.out; diff --git a/packages/circuits/circom/amaci/power/processMessages.circom b/packages/circuits/circom/amaci/power/processMessages.circom index f5c2fd97..0cfb896b 100644 --- a/packages/circuits/circom/amaci/power/processMessages.circom +++ b/packages/circuits/circom/amaci/power/processMessages.circom @@ -64,6 +64,7 @@ template ProcessMessages( signal numSignUps; signal maxVoteOptions; signal isQuadraticCost; + signal maxVotesPerOption; signal input batchStartHash; signal input batchEndHash; @@ -147,6 +148,7 @@ template ProcessMessages( inputHasher.isQuadraticCost ==> isQuadraticCost; inputHasher.maxVoteOptions ==> maxVoteOptions; inputHasher.numSignUps ==> numSignUps; + inputHasher.maxVotesPerOption ==> maxVotesPerOption; inputHasher.hash === inputHash; @@ -243,6 +245,7 @@ template ProcessMessages( processors[i].numSignUps <== numSignUps; processors[i].maxVoteOptions <== maxVoteOptions; + processors[i].maxVotesPerOption <== maxVotesPerOption; processors[i].currentStateRoot <== stateRoots[i + 1]; @@ -337,6 +340,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) { signal input isQuadraticCost; signal input numSignUps; signal input maxVoteOptions; + signal input maxVotesPerOption; signal input currentStateRoot; @@ -376,6 +380,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) { transformer.coordPrivKey <== coordPrivKey; transformer.numSignUps <== numSignUps; transformer.maxVoteOptions <== maxVoteOptions; + transformer.maxVotesPerOption <== maxVotesPerOption; transformer.cmdPollId <== cmdPollId; transformer.expectedPollId <== expectedPollId; transformer.slPubKey[STATE_LEAF_PUB_X_IDX] <== stateLeaf[STATE_LEAF_PUB_X_IDX]; @@ -536,7 +541,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) { /** * Hash all public inputs for the ProcessMessages circuit * This includes: - * - packedVals (maxVoteOptions, numSignUps, isQuadraticCost) + * - packedVals (maxVoteOptions, numSignUps, isQuadraticCost, maxVotesPerOption) * - coordPubKey hash * - batch hashes (start and end) * - state commitments (current and new) @@ -569,15 +574,20 @@ template ProcessMessagesInputHasher() { signal output isQuadraticCost; signal output maxVoteOptions; signal output numSignUps; + signal output maxVotesPerOption; signal output hash; - // 1. Unpack packedVals and ensure that it is valid - component unpack = UnpackElement(3); + // 1. Unpack packedVals and ensure that it is valid. + // Layout (32-bit slots, low to high): + // bits 0-31: maxVoteOptions, bits 32-63: numSignUps, + // bits 64-95: isQuadraticCost, bits 96-127: maxVotesPerOption + component unpack = UnpackElement(4); unpack.in <== packedVals; - maxVoteOptions <== unpack.out[2]; - numSignUps <== unpack.out[1]; - isQuadraticCost <== unpack.out[0]; + maxVoteOptions <== unpack.out[3]; + numSignUps <== unpack.out[2]; + isQuadraticCost <== unpack.out[1]; + maxVotesPerOption <== unpack.out[0]; // 2. Hash coordPubKey component pubKeyHasher = HashLeftRight(); diff --git a/packages/circuits/circom/amaci/power/stateLeafTransformer.circom b/packages/circuits/circom/amaci/power/stateLeafTransformer.circom index 6bb1de92..6766258a 100644 --- a/packages/circuits/circom/amaci/power/stateLeafTransformer.circom +++ b/packages/circuits/circom/amaci/power/stateLeafTransformer.circom @@ -18,6 +18,7 @@ template StateLeafTransformer() { // For the MessageValidator signal input numSignUps; signal input maxVoteOptions; + signal input maxVotesPerOption; // For pollId validation in MessageValidator signal input cmdPollId; @@ -66,6 +67,7 @@ template StateLeafTransformer() { messageValidator.numSignUps <== numSignUps; messageValidator.voteOptionIndex <== cmdVoteOptionIndex; messageValidator.maxVoteOptions <== maxVoteOptions; + messageValidator.maxVotesPerOption <== maxVotesPerOption; messageValidator.originalNonce <== slNonce; messageValidator.nonce <== cmdNonce; messageValidator.cmdPollId <== cmdPollId; diff --git a/packages/circuits/circom/circuits.json b/packages/circuits/circom/circuits.json index 001c4ffd..8f2fb0e4 100644 --- a/packages/circuits/circom/circuits.json +++ b/packages/circuits/circom/circuits.json @@ -1,16 +1,4 @@ { - "ProcessMessages_maci_2-1-5": { - "file": "./maci/power/processMessages", - "template": "ProcessMessages", - "params": [2, 1, 5], - "pubs": ["inputHash"] - }, - "TallyVotes_maci_2-1-1": { - "file": "./maci/power/tallyVotes", - "template": "TallyVotes", - "params": [2, 1, 1], - "pubs": ["inputHash"] - }, "AddNewKey_amaci_2": { "file": "./amaci/power/addNewKey", "template": "AddNewKey", @@ -34,29 +22,5 @@ "template": "TallyVotes", "params": [2, 1, 1], "pubs": ["inputHash"] - }, - "AddNewKey_amaci_9": { - "file": "./amaci/power/addNewKey", - "template": "AddNewKey", - "params": [9], - "pubs": ["inputHash"] - }, - "ProcessDeactivateMessages_amaci_9-125": { - "file": "./amaci/power/processDeactivate", - "template": "ProcessDeactivateMessages", - "params": [9, 125], - "pubs": ["inputHash"] - }, - "ProcessMessages_amaci_9-3-125": { - "file": "./amaci/power/processMessages", - "template": "ProcessMessages", - "params": [9, 3, 125], - "pubs": ["inputHash"] - }, - "TallyVotes_amaci_9-4-3": { - "file": "./amaci/power/tallyVotes", - "template": "TallyVotes", - "params": [9, 4, 3], - "pubs": ["inputHash"] } } diff --git a/packages/circuits/ts/__tests__/DeactivateStatusDetection.test.ts b/packages/circuits/ts/__tests__/DeactivateStatusDetection.test.ts index 0d76886b..c9d086dd 100644 --- a/packages/circuits/ts/__tests__/DeactivateStatusDetection.test.ts +++ b/packages/circuits/ts/__tests__/DeactivateStatusDetection.test.ts @@ -116,6 +116,7 @@ describe('AMACI Deactivate Status Detection', function test() { coordPrivKey, numSignUps: 1n, // Number of registered users maxVoteOptions: 5n, + maxVotesPerOption: 0n, // 0 = no limit (sentinel) cmdPollId: 1n, // Poll ID from the command expectedPollId: 1n, // Expected poll ID for validation diff --git a/packages/circuits/ts/__tests__/MessageValidatorAmaci.test.ts b/packages/circuits/ts/__tests__/MessageValidatorAmaci.test.ts index e025cc7a..60f0d287 100644 --- a/packages/circuits/ts/__tests__/MessageValidatorAmaci.test.ts +++ b/packages/circuits/ts/__tests__/MessageValidatorAmaci.test.ts @@ -1,128 +1,357 @@ -// import { EdDSAPoseidonKeypair } from '@dorafactory/maci-sdk'; -// import { expect } from 'chai'; -// import { type WitnessTester } from 'circomkit'; - -// import { circomkitInstance } from './utils/utils'; - -// describe('AMACI MessageValidator circuit', function test() { -// this.timeout(90000); - -// const keypair = new EdDSAPoseidonKeypair(); - -// // Mock command data (in real usage, these would be properly computed) -// const mockCmd = [BigInt(1), BigInt(2), BigInt(3)]; -// const mockSigR8: [bigint, bigint] = [BigInt(123), BigInt(456)]; -// const mockSigS = BigInt(789); - -// let circuit: WitnessTester< -// [ -// 'stateTreeIndex', -// 'numSignUps', -// 'voteOptionIndex', -// 'maxVoteOptions', -// 'originalNonce', -// 'nonce', -// 'cmd', -// 'pubKey', -// 'sigR8', -// 'sigS', -// 'isQuadraticCost', -// 'currentVoiceCreditBalance', -// 'currentVotesForOption', -// 'voteWeight' -// ], -// ['isValid', 'newBalance'] -// >; - -// before(async () => { -// circuit = await circomkitInstance.WitnessTester('MessageValidator', { -// file: 'amaci/power/messageValidator', -// template: 'MessageValidator' -// }); -// }); - -// it('should accept correct input structure (quadratic cost)', async () => { -// const circuitInputs = { -// stateTreeIndex: 0n, -// numSignUps: 1n, -// voteOptionIndex: 0n, -// maxVoteOptions: 1n, -// originalNonce: 1n, -// nonce: 2n, -// cmd: mockCmd, -// pubKey: keypair.getPublicKey().toPoints() as unknown as [bigint, bigint], -// sigR8: mockSigR8, -// sigS: mockSigS, -// isQuadraticCost: 1n, -// currentVoiceCreditBalance: 100n, -// currentVotesForOption: 0n, -// voteWeight: 9n -// }; - -// // Note: This test will likely fail constraints because we're using mock signature -// // The important part is that the circuit accepts the input structure -// try { -// const witness = await circuit.calculateWitness(circuitInputs); -// expect(witness).to.not.be.undefined; -// } catch (error) { -// // Expected to fail with mock signature -// expect(error).to.not.be.undefined; -// } -// }); - -// it('should accept correct input structure (linear cost)', async () => { -// const circuitInputs = { -// stateTreeIndex: 0n, -// numSignUps: 1n, -// voteOptionIndex: 0n, -// maxVoteOptions: 1n, -// originalNonce: 1n, -// nonce: 2n, -// cmd: mockCmd, -// pubKey: keypair.getPublicKey().toPoints() as unknown as [bigint, bigint], -// sigR8: mockSigR8, -// sigS: mockSigS, -// isQuadraticCost: 0n, // Linear cost -// currentVoiceCreditBalance: 100n, -// currentVotesForOption: 0n, -// voteWeight: 9n -// }; - -// try { -// const witness = await circuit.calculateWitness(circuitInputs); -// expect(witness).to.not.be.undefined; -// } catch (error) { -// // Expected to fail with mock signature -// expect(error).to.not.be.undefined; -// } -// }); - -// it('should handle different vote weights', async () => { -// for (const voteWeight of [1n, 5n, 10n]) { -// const circuitInputs = { -// stateTreeIndex: 0n, -// numSignUps: 1n, -// voteOptionIndex: 0n, -// maxVoteOptions: 1n, -// originalNonce: 1n, -// nonce: 2n, -// cmd: mockCmd, -// pubKey: keypair.getPublicKey().toPoints() as unknown as [bigint, bigint], -// sigR8: mockSigR8, -// sigS: mockSigS, -// isQuadraticCost: 1n, -// currentVoiceCreditBalance: 100n, -// currentVotesForOption: 0n, -// voteWeight -// }; - -// try { -// const witness = await circuit.calculateWitness(circuitInputs); -// expect(witness).to.not.be.undefined; -// } catch (error) { -// // Expected to fail with mock signature -// expect(error).to.not.be.undefined; -// } -// } -// }); -// }); +import { expect } from 'chai'; +import { VoterClient, poseidon, packElement } from '@dorafactory/maci-sdk'; +import { type WitnessTester } from 'circomkit'; + +import { getSignal, circomkitInstance } from './utils/utils'; + +/** + * MessageValidator Circuit Tests for AMACI + * + * Circuit Location: packages/circuits/circom/amaci/power/messageValidator.circom + * + * The AMACI MessageValidator extends the MACI version with two extra checks: + * - PollId matching (cmdPollId === expectedPollId), to prevent cross-poll replay + * - Per-option vote weight cap (maxVotesPerOption), where 0 is a sentinel for + * "no limit" (legacy behavior) + * + * All 8 validations must pass (sum = 8) for isValid to be 1: + * 1. Signature validation + * 2. Sufficient voice credits + * 3. Vote weight bound (< sqrt(field size)) + * 4. Nonce validation + * 5. State leaf index validation + * 6. Vote option index validation + * 7. PollId validation + * 8. Per-option vote weight cap validation + */ +describe('MessageValidator AMACI Circuit Tests', function test() { + this.timeout(300000); + + let circuit: WitnessTester< + [ + 'stateTreeIndex', + 'numSignUps', + 'voteOptionIndex', + 'maxVoteOptions', + 'originalNonce', + 'nonce', + 'cmd', + 'pubKey', + 'sigR8', + 'sigS', + 'isQuadraticCost', + 'currentVoiceCreditBalance', + 'currentVotesForOption', + 'voteWeight', + 'maxVotesPerOption', + 'cmdPollId', + 'expectedPollId' + ], + ['isValid', 'newBalance'] + >; + + let voter: VoterClient; + let keypair: any; + + before(async () => { + circuit = await circomkitInstance.WitnessTester('MessageValidator_AMACI', { + file: 'amaci/power/messageValidator', + template: 'MessageValidator' + }); + + voter = new VoterClient({ + network: 'testnet', + secretKey: 123456n + }); + keypair = voter.getSigner(); + }); + + /** + * Helper function to create a valid command and signature + */ + function createValidCommand( + stateIdx: number, + voIdx: number, + newVotes: bigint, + nonce: number, + newPubKey: [bigint, bigint] = [0n, 0n], + pollId: number = 1 + ) { + const packaged = packElement({ nonce, stateIdx, voIdx, newVotes, pollId }); + const cmd = [packaged, newPubKey[0], newPubKey[1]]; + const msgHash = poseidon(cmd); + const signature = keypair.sign(msgHash); + + return { + cmd, + sigR8: signature.R8 as [bigint, bigint], + sigS: signature.S, + pubKey: keypair.getPublicKey().toPoints() as [bigint, bigint], + pollId: BigInt(pollId) + }; + } + + /** + * Base valid inputs shared by most cases; individual tests override + * only the fields relevant to what they are testing. + */ + function baseInputs(overrides: { + stateTreeIndex?: bigint; + numSignUps?: bigint; + voteOptionIndex?: bigint; + maxVoteOptions?: bigint; + originalNonce?: bigint; + nonce?: bigint; + voteWeight?: bigint; + currentVoiceCreditBalance?: bigint; + currentVotesForOption?: bigint; + isQuadraticCost?: bigint; + maxVotesPerOption?: bigint; + expectedPollId?: bigint; + cmdPollId?: number; + wrongSig?: boolean; + } = {}) { + const stateTreeIndex = overrides.stateTreeIndex ?? 0n; + const numSignUps = overrides.numSignUps ?? 10n; + const voteOptionIndex = overrides.voteOptionIndex ?? 0n; + const maxVoteOptions = overrides.maxVoteOptions ?? 5n; + const originalNonce = overrides.originalNonce ?? 0n; + const nonce = overrides.nonce ?? 1n; + const voteWeight = overrides.voteWeight ?? 5n; + const currentVoiceCreditBalance = overrides.currentVoiceCreditBalance ?? 100n; + const currentVotesForOption = overrides.currentVotesForOption ?? 0n; + const isQuadraticCost = overrides.isQuadraticCost ?? 0n; + const maxVotesPerOption = overrides.maxVotesPerOption ?? 0n; + const expectedPollId = overrides.expectedPollId ?? 1n; + + const { cmd, sigR8, sigS, pubKey, pollId } = createValidCommand( + Number(stateTreeIndex), + Number(voteOptionIndex), + voteWeight, + Number(nonce), + [0n, 0n], + overrides.cmdPollId ?? 1 + ); + + let finalSigR8 = sigR8; + let finalSigS = sigS; + if (overrides.wrongSig) { + const wrongKeypair = new VoterClient({ network: 'testnet', secretKey: 999999n }).getSigner(); + const wrongSignature = wrongKeypair.sign(poseidon(cmd)); + finalSigR8 = wrongSignature.R8 as [bigint, bigint]; + finalSigS = wrongSignature.S; + } + + return { + stateTreeIndex, + numSignUps, + voteOptionIndex, + maxVoteOptions, + originalNonce, + nonce, + cmd, + pubKey, + sigR8: finalSigR8, + sigS: finalSigS, + isQuadraticCost, + currentVoiceCreditBalance, + currentVotesForOption, + voteWeight, + maxVotesPerOption, + cmdPollId: pollId, + expectedPollId + }; + } + + describe('Baseline Validation (maxVotesPerOption = 0, unlimited)', () => { + it('should validate a completely valid message with linear cost', async () => { + const circuitInputs = baseInputs({ voteWeight: 5n, currentVotesForOption: 3n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newBalance')).to.equal(98n); + }); + + it('should validate a completely valid message with quadratic cost', async () => { + const circuitInputs = baseInputs({ + voteWeight: 3n, + currentVotesForOption: 2n, + isQuadraticCost: 1n + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newBalance')).to.equal(95n); + }); + + it('should reject message with invalid stateTreeIndex (too large)', async () => { + const circuitInputs = baseInputs({ stateTreeIndex: 11n, numSignUps: 10n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should reject message with invalid voteOptionIndex (too large)', async () => { + const circuitInputs = baseInputs({ voteOptionIndex: 5n, maxVoteOptions: 5n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should reject message with incorrect nonce', async () => { + const circuitInputs = baseInputs({ originalNonce: 0n, nonce: 3n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should reject message with invalid signature', async () => { + const circuitInputs = baseInputs({ wrongSig: true }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should reject message with insufficient balance', async () => { + const circuitInputs = baseInputs({ voteWeight: 50n, currentVoiceCreditBalance: 10n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + }); + + describe('PollId Validation (AMACI-specific)', () => { + it('should reject message when cmdPollId does not match expectedPollId', async () => { + const circuitInputs = baseInputs({ cmdPollId: 2, expectedPollId: 1n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal( + 0n, + 'Message should be invalid (pollId mismatch)' + ); + }); + + it('should accept message when cmdPollId matches expectedPollId', async () => { + const circuitInputs = baseInputs({ cmdPollId: 7, expectedPollId: 7n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + }); + + describe('Per-Option Vote Cap Validation (maxVotesPerOption)', () => { + it('should accept any vote weight within balance when cap is 0 (sentinel: unlimited)', async () => { + const circuitInputs = baseInputs({ voteWeight: 90n, maxVotesPerOption: 0n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + + it('should accept a vote exactly at the cap', async () => { + const circuitInputs = baseInputs({ voteWeight: 10n, maxVotesPerOption: 10n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + + it('should reject a vote exceeding the cap by 1', async () => { + const circuitInputs = baseInputs({ voteWeight: 11n, maxVotesPerOption: 10n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should reject an over-cap vote under quadratic cost even when balance is sufficient', async () => { + // 6 votes cost 36 credits, affordable with balance 100, but over a cap of 5 + const circuitInputs = baseInputs({ + voteWeight: 6n, + maxVotesPerOption: 5n, + isQuadraticCost: 1n, + currentVoiceCreditBalance: 100n + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should accept a vote at the cap under quadratic cost', async () => { + const circuitInputs = baseInputs({ + voteWeight: 5n, + maxVotesPerOption: 5n, + isQuadraticCost: 1n, + currentVoiceCreditBalance: 100n + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newBalance')).to.equal(75n); + }); + + it('should accept a vote of 0 regardless of a nonzero cap', async () => { + const circuitInputs = baseInputs({ voteWeight: 0n, maxVotesPerOption: 1n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + + it('should accept a vote at the maximum 32-bit cap value', async () => { + const circuitInputs = baseInputs({ + voteWeight: 1000n, + maxVotesPerOption: 0xffffffffn, + currentVoiceCreditBalance: 10000n + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + + it('should reject when both the cap and another validation (nonce) fail simultaneously', async () => { + const circuitInputs = baseInputs({ + voteWeight: 11n, + maxVotesPerOption: 10n, + originalNonce: 0n, + nonce: 3n // wrong nonce, in addition to the over-cap vote + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal( + 0n, + 'Message should be invalid regardless of how many checks fail' + ); + }); + }); +}); diff --git a/packages/circuits/ts/__tests__/ProcessMessagesAmaciMaxVotesPerOption.test.ts b/packages/circuits/ts/__tests__/ProcessMessagesAmaciMaxVotesPerOption.test.ts new file mode 100644 index 00000000..8e2afa37 --- /dev/null +++ b/packages/circuits/ts/__tests__/ProcessMessagesAmaciMaxVotesPerOption.test.ts @@ -0,0 +1,252 @@ +import { expect } from 'chai'; +import { OperatorClient, VoterClient } from '@dorafactory/maci-sdk'; +import { type WitnessTester } from 'circomkit'; + +import { circomkitInstance } from './utils/utils'; + +/** + * ProcessMessages Circuit Test (AMACI): max votes per option cap + * + * Verifies the per-option vote weight cap (`maxVotesPerOption`) added to the + * AMACI process circuit: + * - packedVals carries the cap in bits 96-127 + * - cap = 0 is a sentinel meaning "no limit" (legacy behavior) + * - a message with newVotes > cap is invalidated (state unchanged), exactly + * mirroring the SDK OperatorClient logic + * + * Circuit Location: packages/circuits/circom/amaci/power/processMessages.circom + * SDK Location: packages/sdk/src/operator.ts (checkCommandNow + packedVals) + */ + +describe('ProcessMessages AMACI MaxVotesPerOption Tests', function () { + this.timeout(600000); // 10 minute timeout + + let processMessagesCircuit: WitnessTester; + + // Test parameters (must match between circuit and SDK) + const stateTreeDepth = 2; + const voteOptionTreeDepth = 2; + const batchSize = 5; + const maxVoteOptions = 5; + const initialBalance = 100; + + before(async () => { + processMessagesCircuit = await circomkitInstance.WitnessTester('ProcessMessages_AMACI', { + file: 'amaci/power/processMessages', + template: 'ProcessMessages', + params: [stateTreeDepth, voteOptionTreeDepth, batchSize] + }); + }); + + function createTestSetup({ + isQuadraticCost = false, + maxVotesPerOption = 0n + }: { + isQuadraticCost?: boolean; + maxVotesPerOption?: bigint; + } = {}) { + const operator = new OperatorClient({ + network: 'testnet', + secretKey: 111111n + }); + + operator.initRound({ + stateTreeDepth, + intStateTreeDepth: 1, + voteOptionTreeDepth, + batchSize, + maxVoteOptions, + maxVotesPerOption, + pollId: 1, + isQuadraticCost, + isAmaci: true + }); + + const voters = [ + new VoterClient({ network: 'testnet', secretKey: 222222n }), + new VoterClient({ network: 'testnet', secretKey: 333333n }), + new VoterClient({ network: 'testnet', secretKey: 444444n }) + ]; + + voters.forEach((voter, idx) => { + const pubKey = voter.getPubkey().toPoints(); + operator.updateStateTree(idx, pubKey, initialBalance); + }); + + return { operator, voters }; + } + + function submitVotes( + operator: OperatorClient, + voters: VoterClient[], + votes: Array<{ voterIdx: number; options: Array<{ idx: number; vc: number }> }> + ) { + const coordPubKey = operator.getPubkey().toPoints(); + + votes.forEach(({ voterIdx, options }) => { + const voter = voters[voterIdx]; + const votePayload = voter.buildVotePayload({ + stateIdx: voterIdx, + operatorPubkey: coordPubKey, + selectedOptions: options, + pollId: 1 + }); + + for (const payload of votePayload) { + const message = payload.msg.map((m) => BigInt(m)); + const encPubKey = payload.encPubkeys.map((k) => BigInt(k)) as [bigint, bigint]; + operator.pushMessage(message, encPubKey); + } + }); + } + + async function processAndVerify(operator: OperatorClient, newStateSalt: bigint) { + operator.endVotePeriod(); + const { input } = await operator.processMessages({ newStateSalt }); + const witness = await processMessagesCircuit.calculateWitness(input as any); + await processMessagesCircuit.expectConstraintPass(witness); + return input; + } + + describe('packedVals encoding', () => { + it('should place the cap in bits 96-127 of packedVals', async () => { + const cap = 10n; + const { operator, voters } = createTestSetup({ maxVotesPerOption: cap }); + + submitVotes(operator, voters, [{ voterIdx: 0, options: [{ idx: 1, vc: 5 }] }]); + + const input = await processAndVerify(operator, 1001n); + + const packedVals = BigInt(input.packedVals); + expect(packedVals & 0xffffffffn).to.equal(BigInt(maxVoteOptions), 'bits 0-31'); + expect((packedVals >> 32n) & 0xffffffffn).to.equal(3n, 'bits 32-63 = numSignUps'); + expect((packedVals >> 64n) & 0xffffffffn).to.equal(0n, 'bits 64-95 = isQuadraticCost'); + expect((packedVals >> 96n) & 0xffffffffn).to.equal(cap, 'bits 96-127 = maxVotesPerOption'); + }); + }); + + describe('sentinel 0 = no limit (legacy behavior)', () => { + it('should accept any vote weight within balance when cap is 0', async () => { + const { operator, voters } = createTestSetup({ maxVotesPerOption: 0n }); + + // Spend the whole budget on one option — legal without a cap + submitVotes(operator, voters, [ + { voterIdx: 0, options: [{ idx: 1, vc: initialBalance }] } + ]); + + await processAndVerify(operator, 2001n); + + const leaf = operator.stateLeaves.get(0)!; + expect(leaf.voTree.leaf(1)).to.equal(BigInt(initialBalance), 'vote applied'); + expect(leaf.balance).to.equal(0n, 'full budget spent'); + }); + }); + + describe('1P1V with cap', () => { + it('should accept a vote exactly at the cap', async () => { + const cap = 10n; + const { operator, voters } = createTestSetup({ maxVotesPerOption: cap }); + + submitVotes(operator, voters, [{ voterIdx: 0, options: [{ idx: 2, vc: 10 }] }]); + + await processAndVerify(operator, 3001n); + + const leaf = operator.stateLeaves.get(0)!; + expect(leaf.voTree.leaf(2)).to.equal(10n, 'at-cap vote applied'); + expect(leaf.balance).to.equal(BigInt(initialBalance) - 10n, 'balance deducted'); + }); + + it('should invalidate a vote exceeding the cap by 1 (state unchanged)', async () => { + const cap = 10n; + const { operator, voters } = createTestSetup({ maxVotesPerOption: cap }); + + submitVotes(operator, voters, [{ voterIdx: 0, options: [{ idx: 2, vc: 11 }] }]); + + await processAndVerify(operator, 3002n); + + const leaf = operator.stateLeaves.get(0)!; + expect(leaf.voTree.leaf(2)).to.equal(0n, 'over-cap vote NOT applied'); + expect(leaf.balance).to.equal(BigInt(initialBalance), 'balance unchanged'); + }); + + it('should handle mixed valid/invalid votes from multiple voters in one batch', async () => { + const cap = 10n; + const { operator, voters } = createTestSetup({ maxVotesPerOption: cap }); + + submitVotes(operator, voters, [ + { voterIdx: 0, options: [{ idx: 0, vc: 10 }] }, // at cap: valid + { voterIdx: 1, options: [{ idx: 0, vc: 30 }] }, // over cap: invalid + { voterIdx: 2, options: [{ idx: 3, vc: 1 }] } // under cap: valid + ]); + + await processAndVerify(operator, 3003n); + + expect(operator.stateLeaves.get(0)!.voTree.leaf(0)).to.equal(10n); + expect(operator.stateLeaves.get(1)!.voTree.leaf(0)).to.equal(0n); + expect(operator.stateLeaves.get(1)!.balance).to.equal(BigInt(initialBalance)); + expect(operator.stateLeaves.get(2)!.voTree.leaf(3)).to.equal(1n); + }); + }); + + describe('QV with cap', () => { + it('should cap the vote weight (not the quadratic cost)', async () => { + const cap = 5n; + const { operator, voters } = createTestSetup({ + isQuadraticCost: true, + maxVotesPerOption: cap + }); + + // 5 votes cost 25 credits in QV — at cap, valid + submitVotes(operator, voters, [{ voterIdx: 0, options: [{ idx: 1, vc: 5 }] }]); + + await processAndVerify(operator, 4001n); + + const leaf = operator.stateLeaves.get(0)!; + expect(leaf.voTree.leaf(1)).to.equal(5n, 'at-cap QV vote applied'); + expect(leaf.balance).to.equal(BigInt(initialBalance) - 25n, 'quadratic cost deducted'); + }); + + it('should invalidate an over-cap QV vote even when balance is sufficient', async () => { + const cap = 5n; + const { operator, voters } = createTestSetup({ + isQuadraticCost: true, + maxVotesPerOption: cap + }); + + // 6 votes cost 36 credits — affordable with balance 100, but over the cap + submitVotes(operator, voters, [{ voterIdx: 0, options: [{ idx: 1, vc: 6 }] }]); + + await processAndVerify(operator, 4002n); + + const leaf = operator.stateLeaves.get(0)!; + expect(leaf.voTree.leaf(1)).to.equal(0n, 'over-cap QV vote NOT applied'); + expect(leaf.balance).to.equal(BigInt(initialBalance), 'balance unchanged'); + }); + }); + + describe('multiple options per ballot', () => { + it('should validate each message independently against the cap', async () => { + const cap = 10n; + const { operator, voters } = createTestSetup({ maxVotesPerOption: cap }); + + // One ballot spreading votes: options 0/1 within cap, option 2 over cap + submitVotes(operator, voters, [ + { + voterIdx: 0, + options: [ + { idx: 0, vc: 10 }, + { idx: 1, vc: 7 }, + { idx: 2, vc: 12 } + ] + } + ]); + + await processAndVerify(operator, 5001n); + + const leaf = operator.stateLeaves.get(0)!; + expect(leaf.voTree.leaf(0)).to.equal(10n); + expect(leaf.voTree.leaf(1)).to.equal(7n); + expect(leaf.voTree.leaf(2)).to.equal(0n, 'over-cap message invalidated'); + }); + }); +}); diff --git a/packages/circuits/ts/__tests__/StateLeafTransformerAmaci.test.ts b/packages/circuits/ts/__tests__/StateLeafTransformerAmaci.test.ts index fa345860..68e3ccc2 100644 --- a/packages/circuits/ts/__tests__/StateLeafTransformerAmaci.test.ts +++ b/packages/circuits/ts/__tests__/StateLeafTransformerAmaci.test.ts @@ -1,172 +1,341 @@ -// import { EdDSAPoseidonKeypair } from '@dorafactory/maci-sdk'; -// import { expect } from 'chai'; -// import { type WitnessTester } from 'circomkit'; - -// import { circomkitInstance } from './utils/utils'; - -// describe('AMACI StateLeafTransformer circuit', function test() { -// this.timeout(90000); - -// // Variables needed for testing -// const coordKeypair = new EdDSAPoseidonKeypair(); -// const coordPrivKey = coordKeypair.getPrivateKey(); -// const stateLeafKeypair = new EdDSAPoseidonKeypair(); -// const newPublicKey = new EdDSAPoseidonKeypair().getPublicKey(); - -// const totalSignups = 25n; -// const maxVoteOptions = 25n; -// const stateLeafVoiceCreditBalance = BigInt(100); -// const stateLeafNonce = BigInt(0); -// const currentVotesForOption = BigInt(0); - -// // ElGamal ciphertext components (c1, c2) - for testing, we use simple values -// // In real usage, these would be properly encrypted values -// // For active state: encrypt 0 (even x-coordinate) -// // For deactivated state: encrypt 1 (odd x-coordinate) -// const c1 = [BigInt(1), BigInt(2)]; -// const c2 = [BigInt(3), BigInt(4)]; - -// // Mock command data -// const cmdStateIndex = BigInt(1); -// const cmdVoteOptionIndex = BigInt(0); -// const cmdNewVoteWeight = BigInt(9); -// const cmdNonce = BigInt(1); - -// // Mock signature (in real usage, this would be computed correctly) -// const cmdSigR8: [bigint, bigint] = [BigInt(123), BigInt(456)]; -// const cmdSigS = BigInt(789); - -// // Mock packed command (in real usage, this would be computed correctly) -// const packedCommand = [BigInt(1), BigInt(2), BigInt(3)]; - -// let circuit: WitnessTester< -// [ -// 'isQuadraticCost', -// 'coordPrivKey', -// 'numSignUps', -// 'maxVoteOptions', -// 'slPubKey', -// 'slVoiceCreditBalance', -// 'slNonce', -// 'slC1', -// 'slC2', -// 'currentVotesForOption', -// 'cmdStateIndex', -// 'cmdNewPubKey', -// 'cmdVoteOptionIndex', -// 'cmdNewVoteWeight', -// 'cmdNonce', -// 'cmdSigR8', -// 'cmdSigS', -// 'packedCommand', -// 'deactivate' -// ], -// ['newSlPubKey', 'newSlNonce', 'isValid', 'newBalance'] -// >; - -// before(async () => { -// circuit = await circomkitInstance.WitnessTester('StateLeafTransformer', { -// file: 'amaci/power/stateLeafTransformer', -// template: 'StateLeafTransformer' -// }); -// }); - -// it('should accept correct input structure', async () => { -// const circuitInputs = { -// isQuadraticCost: 1n, -// coordPrivKey: coordPrivKey as bigint, -// numSignUps: totalSignups, -// maxVoteOptions, -// slPubKey: stateLeafKeypair.getPublicKey().toPoints() as unknown as [bigint, bigint], -// slVoiceCreditBalance: stateLeafVoiceCreditBalance, -// slNonce: stateLeafNonce, -// slC1: c1, -// slC2: c2, -// currentVotesForOption, -// cmdStateIndex, -// cmdNewPubKey: newPublicKey.toPoints() as unknown as [bigint, bigint], -// cmdVoteOptionIndex, -// cmdNewVoteWeight, -// cmdNonce, -// cmdSigR8, -// cmdSigS, -// packedCommand, -// deactivate: 0n // User is active (not deactivated) -// }; - -// // Note: This test will likely fail constraints because we're using mock signature -// // In a real scenario, the signature would be properly computed -// try { -// const witness = await circuit.calculateWitness(circuitInputs); -// // If we get here, input structure is correct -// expect(witness).to.not.be.undefined; -// } catch (error) { -// // Expected to fail with mock data, but structure should be accepted -// expect(error).to.not.be.undefined; -// } -// }); - -// it('should accept deactivate flag', async () => { -// const circuitInputs = { -// isQuadraticCost: 1n, -// coordPrivKey: coordPrivKey as bigint, -// numSignUps: totalSignups, -// maxVoteOptions, -// slPubKey: stateLeafKeypair.getPublicKey().toPoints() as unknown as [bigint, bigint], -// slVoiceCreditBalance: stateLeafVoiceCreditBalance, -// slNonce: stateLeafNonce, -// slC1: c1, -// slC2: c2, -// currentVotesForOption, -// cmdStateIndex, -// cmdNewPubKey: newPublicKey.toPoints() as unknown as [bigint, bigint], -// cmdVoteOptionIndex, -// cmdNewVoteWeight, -// cmdNonce, -// cmdSigR8, -// cmdSigS, -// packedCommand, -// deactivate: 1n // User is deactivated -// }; - -// try { -// const witness = await circuit.calculateWitness(circuitInputs); -// expect(witness).to.not.be.undefined; -// } catch (error) { -// // Expected to fail with mock data -// expect(error).to.not.be.undefined; -// } -// }); - -// it('should work with non-quadratic cost flag', async () => { -// const circuitInputs = { -// isQuadraticCost: 0n, // Linear cost -// coordPrivKey: coordPrivKey as bigint, -// numSignUps: totalSignups, -// maxVoteOptions, -// slPubKey: stateLeafKeypair.getPublicKey().toPoints() as unknown as [bigint, bigint], -// slVoiceCreditBalance: stateLeafVoiceCreditBalance, -// slNonce: stateLeafNonce, -// slC1: c1, -// slC2: c2, -// currentVotesForOption, -// cmdStateIndex, -// cmdNewPubKey: newPublicKey.toPoints() as unknown as [bigint, bigint], -// cmdVoteOptionIndex, -// cmdNewVoteWeight, -// cmdNonce, -// cmdSigR8, -// cmdSigS, -// packedCommand, -// deactivate: 0n -// }; - -// try { -// const witness = await circuit.calculateWitness(circuitInputs); -// expect(witness).to.not.be.undefined; -// } catch (error) { -// // Expected to fail with mock data -// expect(error).to.not.be.undefined; -// } -// }); -// }); +import { expect } from 'chai'; +import { VoterClient, OperatorClient, poseidon, packElement, encryptOdevity } from '@dorafactory/maci-sdk'; +import { type WitnessTester } from 'circomkit'; + +import { getSignal, circomkitInstance } from './utils/utils'; + +/** + * StateLeafTransformer Circuit Tests for AMACI + * + * Circuit Location: packages/circuits/circom/amaci/power/stateLeafTransformer.circom + * + * The AMACI StateLeafTransformer extends the MACI version with: + * - ElGamal-based active/deactivate status check (slC1/slC2/coordPrivKey/deactivate) + * - Per-option vote weight cap (maxVotesPerOption, 0 = unlimited) + * - PollId matching (cmdPollId/expectedPollId), delegated to MessageValidator + * + * Overall validity requires all three of: + * 1 - decryptIsActive.isOdd (state leaf is active, i.e. NOT deactivated) + * activate.out (the `deactivate` input signal itself is 0) + * messageValidator.isValid (command passes all 8 MessageValidator checks) + * to sum to 3. + */ +describe('StateLeafTransformer AMACI Circuit Tests', function test() { + this.timeout(300000); + + let circuit: WitnessTester< + [ + 'isQuadraticCost', + 'coordPrivKey', + 'numSignUps', + 'maxVoteOptions', + 'maxVotesPerOption', + 'cmdPollId', + 'expectedPollId', + 'slPubKey', + 'slVoiceCreditBalance', + 'slNonce', + 'slC1', + 'slC2', + 'currentVotesForOption', + 'cmdStateIndex', + 'cmdNewPubKey', + 'cmdVoteOptionIndex', + 'cmdNewVoteWeight', + 'cmdNonce', + 'cmdSigR8', + 'cmdSigS', + 'packedCommand', + 'deactivate' + ], + ['newSlPubKey', 'newSlNonce', 'isValid', 'newBalance'] + >; + + let voter: VoterClient; + let keypair: any; + let coordinator: OperatorClient; + + before(async () => { + circuit = await circomkitInstance.WitnessTester('StateLeafTransformer_AMACI', { + file: 'amaci/power/stateLeafTransformer', + template: 'StateLeafTransformer' + }); + + voter = new VoterClient({ + network: 'testnet', + secretKey: 123456n + }); + keypair = voter.getSigner(); + + coordinator = new OperatorClient({ + network: 'testnet', + secretKey: 111111n + }); + }); + + function createValidCommand( + stateIdx: number, + voIdx: number, + newVotes: bigint, + nonce: number, + newPubKey: [bigint, bigint] = [0n, 0n], + pollId: number = 1 + ) { + const packaged = packElement({ nonce, stateIdx, voIdx, newVotes, pollId }); + const cmd = [packaged, newPubKey[0], newPubKey[1]]; + const msgHash = poseidon(cmd); + const signature = keypair.sign(msgHash); + + return { + cmd, + sigR8: signature.R8 as [bigint, bigint], + sigS: signature.S, + pollId: BigInt(pollId) + }; + } + + // The simplest "active" ciphertext: c1 = c2 = [0, 0] decrypts to x = 0 + // (even), i.e. isOdd = 0, regardless of coordPrivKey. + const ACTIVE_C1: [bigint, bigint] = [0n, 0n]; + const ACTIVE_C2: [bigint, bigint] = [0n, 0n]; + // Independent of `coordinator` (which is only created inside `before`), + // so this can be evaluated eagerly at describe-body collection time. + const coordPrivKey = new OperatorClient({ network: 'testnet', secretKey: 111111n }) + .getSigner() + .getFormatedPrivKey(); + + function baseInputs(overrides: { + isQuadraticCost?: bigint; + numSignUps?: bigint; + maxVoteOptions?: bigint; + maxVotesPerOption?: bigint; + expectedPollId?: bigint; + cmdPollId?: number; + slVoiceCreditBalance?: bigint; + slNonce?: bigint; + slC1?: [bigint, bigint]; + slC2?: [bigint, bigint]; + currentVotesForOption?: bigint; + cmdStateIndex?: bigint; + cmdNewPubKey?: [bigint, bigint]; + cmdVoteOptionIndex?: bigint; + cmdNewVoteWeight?: bigint; + cmdNonce?: bigint; + deactivate?: bigint; + wrongSig?: boolean; + } = {}) { + const isQuadraticCost = overrides.isQuadraticCost ?? 0n; + const numSignUps = overrides.numSignUps ?? 10n; + const maxVoteOptions = overrides.maxVoteOptions ?? 5n; + const maxVotesPerOption = overrides.maxVotesPerOption ?? 0n; + const expectedPollId = overrides.expectedPollId ?? 1n; + const slPubKey = keypair.getPublicKey().toPoints() as [bigint, bigint]; + const slVoiceCreditBalance = overrides.slVoiceCreditBalance ?? 100n; + const slNonce = overrides.slNonce ?? 0n; + const slC1 = overrides.slC1 ?? ACTIVE_C1; + const slC2 = overrides.slC2 ?? ACTIVE_C2; + const currentVotesForOption = overrides.currentVotesForOption ?? 0n; + const cmdStateIndex = overrides.cmdStateIndex ?? 0n; + const cmdNewPubKey = overrides.cmdNewPubKey ?? ([111222333n, 444555666n] as [bigint, bigint]); + const cmdVoteOptionIndex = overrides.cmdVoteOptionIndex ?? 1n; + const cmdNewVoteWeight = overrides.cmdNewVoteWeight ?? 10n; + const cmdNonce = overrides.cmdNonce ?? slNonce + 1n; + const deactivate = overrides.deactivate ?? 0n; + + const { cmd, sigR8, sigS, pollId } = createValidCommand( + Number(cmdStateIndex), + Number(cmdVoteOptionIndex), + cmdNewVoteWeight, + Number(cmdNonce), + cmdNewPubKey, + overrides.cmdPollId ?? 1 + ); + + let finalSigR8 = sigR8; + let finalSigS = sigS; + if (overrides.wrongSig) { + const wrongSignature = keypair.sign(poseidon([cmd[0] + 1n, cmd[1], cmd[2]])); + finalSigR8 = wrongSignature.R8 as [bigint, bigint]; + finalSigS = wrongSignature.S; + } + + return { + isQuadraticCost, + coordPrivKey, + numSignUps, + maxVoteOptions, + maxVotesPerOption, + cmdPollId: pollId, + expectedPollId, + slPubKey, + slVoiceCreditBalance, + slNonce, + slC1, + slC2, + currentVotesForOption, + cmdStateIndex, + cmdNewPubKey, + cmdVoteOptionIndex, + cmdNewVoteWeight, + cmdNonce, + cmdSigR8: finalSigR8, + cmdSigS: finalSigS, + packedCommand: cmd, + deactivate + }; + } + + describe('Baseline Validation (active user, maxVotesPerOption = 0)', () => { + it('should update state leaf for a valid first vote (linear cost)', async () => { + const circuitInputs = baseInputs({ cmdNewVoteWeight: 10n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newSlNonce')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newBalance')).to.equal(90n); + }); + + it('should update state leaf for a valid vote (quadratic cost)', async () => { + const circuitInputs = baseInputs({ isQuadraticCost: 1n, cmdNewVoteWeight: 5n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newBalance')).to.equal(75n); // 100 - 5^2 + }); + + it('should preserve state when the command signature is invalid', async () => { + const circuitInputs = baseInputs({ wrongSig: true }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + expect(await getSignal(circuit, witness, 'newSlNonce')).to.equal(circuitInputs.slNonce); + }); + + it('should preserve state when nonce is incorrect', async () => { + const circuitInputs = baseInputs({ slNonce: 5n, cmdNonce: 7n }); // should be 6 + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + expect(await getSignal(circuit, witness, 'newSlNonce')).to.equal(5n); + }); + }); + + describe('Deactivation Status Interaction (ElGamal)', () => { + it('should reject the command when the state leaf ciphertext decrypts as deactivated', async () => { + const coordPubKey = coordinator.getPubkey().toPoints() as [bigint, bigint]; + const deactivated = encryptOdevity(true, coordPubKey, 987654321n); + + const circuitInputs = baseInputs({ + slC1: [deactivated.c1.x, deactivated.c1.y], + slC2: [deactivated.c2.x, deactivated.c2.y] + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal( + 0n, + 'A deactivated user cannot vote, even with an otherwise valid+in-cap command' + ); + expect(await getSignal(circuit, witness, 'newSlNonce')).to.equal(circuitInputs.slNonce); + }); + + it('should accept the command when the state leaf ciphertext decrypts as active', async () => { + const coordPubKey = coordinator.getPubkey().toPoints() as [bigint, bigint]; + const active = encryptOdevity(false, coordPubKey, 123456789n); + + const circuitInputs = baseInputs({ + slC1: [active.c1.x, active.c1.y], + slC2: [active.c2.x, active.c2.y] + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + + it('should reject the command when the `deactivate` input flag itself is set', async () => { + const circuitInputs = baseInputs({ deactivate: 1n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + }); + + describe('Per-Option Vote Cap Enforcement (maxVotesPerOption)', () => { + it('should accept any vote weight within balance when cap is 0 (unlimited)', async () => { + const circuitInputs = baseInputs({ maxVotesPerOption: 0n, cmdNewVoteWeight: 90n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + }); + + it('should update state leaf for a vote exactly at the cap', async () => { + const circuitInputs = baseInputs({ maxVotesPerOption: 10n, cmdNewVoteWeight: 10n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(1n); + expect(await getSignal(circuit, witness, 'newSlNonce')).to.equal(circuitInputs.cmdNonce); + }); + + it('should preserve state (reject) for a vote exceeding the cap by 1', async () => { + const circuitInputs = baseInputs({ maxVotesPerOption: 10n, cmdNewVoteWeight: 11n }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + expect(await getSignal(circuit, witness, 'newSlNonce')).to.equal(circuitInputs.slNonce); + + const newSlPubKey0 = await getSignal(circuit, witness, 'newSlPubKey[0]'); + expect(newSlPubKey0).to.equal(circuitInputs.slPubKey[0], 'Should preserve original public key'); + }); + + it('should reject an over-cap vote under quadratic cost even when balance is sufficient', async () => { + const circuitInputs = baseInputs({ + isQuadraticCost: 1n, + maxVotesPerOption: 5n, + cmdNewVoteWeight: 6n, // costs 36, affordable, but over the cap of 5 + slVoiceCreditBalance: 100n + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + + it('should combine cap enforcement with active deactivation status correctly', async () => { + // Over-cap AND deactivated: still simply invalid, no double-counting weirdness. + const coordPubKey = coordinator.getPubkey().toPoints() as [bigint, bigint]; + const deactivated = encryptOdevity(true, coordPubKey, 555555555n); + + const circuitInputs = baseInputs({ + maxVotesPerOption: 10n, + cmdNewVoteWeight: 20n, + slC1: [deactivated.c1.x, deactivated.c1.y], + slC2: [deactivated.c2.x, deactivated.c2.y] + }); + + const witness = await circuit.calculateWitness(circuitInputs); + await circuit.expectConstraintPass(witness); + + expect(await getSignal(circuit, witness, 'isValid')).to.equal(0n); + }); + }); +}); diff --git a/packages/circuits/ts/generate-logs.ts b/packages/circuits/ts/generate-logs.ts index 7a08c6b8..473102ca 100644 --- a/packages/circuits/ts/generate-logs.ts +++ b/packages/circuits/ts/generate-logs.ts @@ -8,8 +8,17 @@ import { OperatorClient, VoterClient, stringizing, adaptToUncompressed } from '@ // CLI options // --local-addkey Use locally compiled AddNewKey_amaci_2 // artifacts instead of downloading from S3 +// --local Use locally compiled artifacts (from circomkit's +// `generate-zkeys`) for ALL 4 circuits (AddNewKey, +// ProcessDeactivateMessages, ProcessMessages, TallyVotes) +// instead of downloading the remote v5 tarball. Required +// whenever the circuits themselves changed (e.g. the +// maxVotesPerOption feature), since the remote v5 +// artifacts are built from an older circuit version and +// are incompatible with the current circom/SDK code. // ============================================================ -const USE_LOCAL_ADDKEY = process.argv.includes('--local-addkey'); +const USE_LOCAL_ALL = process.argv.includes('--local'); +const USE_LOCAL_ADDKEY = USE_LOCAL_ALL || process.argv.includes('--local-addkey'); // Build paths configuration const BUILD_DIR = path.join(__dirname, '../build'); @@ -19,6 +28,23 @@ const LOCAL_ADDKEY_DIR = path.join(BUILD_DIR, 'AddNewKey_amaci_2'); const LOCAL_ADDKEY_WASM = path.join(LOCAL_ADDKEY_DIR, 'AddNewKey_amaci_2_js', 'AddNewKey_amaci_2.wasm'); const LOCAL_ADDKEY_ZKEY = path.join(LOCAL_ADDKEY_DIR, 'AddNewKey_amaci_2.0.zkey'); +// ---------- Local compiled artifacts for deactivate/msg/tally ---------- +const LOCAL_DEACTIVATE_DIR = path.join(BUILD_DIR, 'ProcessDeactivateMessages_amaci_2-5'); +const LOCAL_DEACTIVATE_WASM = path.join( + LOCAL_DEACTIVATE_DIR, + 'ProcessDeactivateMessages_amaci_2-5_js', + 'ProcessDeactivateMessages_amaci_2-5.wasm' +); +const LOCAL_DEACTIVATE_ZKEY = path.join(LOCAL_DEACTIVATE_DIR, 'ProcessDeactivateMessages_amaci_2-5.0.zkey'); + +const LOCAL_MSG_DIR = path.join(BUILD_DIR, 'ProcessMessages_amaci_2-1-5'); +const LOCAL_MSG_WASM = path.join(LOCAL_MSG_DIR, 'ProcessMessages_amaci_2-1-5_js', 'ProcessMessages_amaci_2-1-5.wasm'); +const LOCAL_MSG_ZKEY = path.join(LOCAL_MSG_DIR, 'ProcessMessages_amaci_2-1-5.0.zkey'); + +const LOCAL_TALLY_DIR = path.join(BUILD_DIR, 'TallyVotes_amaci_2-1-1'); +const LOCAL_TALLY_WASM = path.join(LOCAL_TALLY_DIR, 'TallyVotes_amaci_2-1-1_js', 'TallyVotes_amaci_2-1-1.wasm'); +const LOCAL_TALLY_ZKEY = path.join(LOCAL_TALLY_DIR, 'TallyVotes_amaci_2-1-1.0.zkey'); + // ---------- v5 remote zkey/wasm artifacts (amaci_2-1-1-5) ---------- // The tar https://...amaci_2-1-1-5_v5_zkeys.tar.gz extracts to build/2-1-1-5/ // with file names: deactivate.wasm/zkey, msg.wasm/zkey, tally.wasm/zkey @@ -29,22 +55,19 @@ const ZKEYS_V5_URLS = { amaciZkeysTar: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v5_zkeys.tar.gz' }; -// Deactivate circuit paths -const DEACTIVATE_WASM = path.join(ZKEYS_V5_BASE, 'deactivate.wasm'); -const DEACTIVATE_ZKEY = path.join(ZKEYS_V5_BASE, 'deactivate.zkey'); +// Deactivate/ProcessMessages/TallyVotes circuit paths – resolved at runtime +// based on --local flag (remote v5 tar vs locally compiled circomkit artifacts) +let DEACTIVATE_WASM: string; +let DEACTIVATE_ZKEY: string; +let MSG_WASM: string; +let MSG_ZKEY: string; +let TALLY_WASM: string; +let TALLY_ZKEY: string; // AddKey circuit paths – resolved at runtime based on --local-addkey flag let ADDKEY_WASM: string; let ADDKEY_ZKEY: string; -// ProcessMessages circuit paths (file name in tar: msg.wasm / msg.zkey) -const MSG_WASM = path.join(ZKEYS_V5_BASE, 'msg.wasm'); -const MSG_ZKEY = path.join(ZKEYS_V5_BASE, 'msg.zkey'); - -// TallyVotes circuit paths (file name in tar: tally.wasm / tally.zkey) -const TALLY_WASM = path.join(ZKEYS_V5_BASE, 'tally.wasm'); -const TALLY_ZKEY = path.join(ZKEYS_V5_BASE, 'tally.zkey'); - async function downloadFile(url: string, destPath: string): Promise { const res = await fetch(url); if (!res.ok) throw new Error(`Failed to download ${url}: ${res.status}`); @@ -69,17 +92,48 @@ function checkLocalAddkeyArtifacts(): void { console.log(' zkey:', LOCAL_ADDKEY_ZKEY); } -const REQUIRED_REMOTE_ARTIFACTS = [ - { name: 'deactivate.wasm', p: DEACTIVATE_WASM }, - { name: 'deactivate.zkey', p: DEACTIVATE_ZKEY }, - { name: 'msg.wasm', p: MSG_WASM }, - { name: 'msg.zkey', p: MSG_ZKEY }, - { name: 'tally.wasm', p: TALLY_WASM }, - { name: 'tally.zkey', p: TALLY_ZKEY } -]; +function checkLocalAllArtifacts(): void { + const localArtifacts = [ + { name: 'ProcessDeactivateMessages wasm', p: LOCAL_DEACTIVATE_WASM }, + { name: 'ProcessDeactivateMessages zkey', p: LOCAL_DEACTIVATE_ZKEY }, + { name: 'ProcessMessages wasm', p: LOCAL_MSG_WASM }, + { name: 'ProcessMessages zkey', p: LOCAL_MSG_ZKEY }, + { name: 'TallyVotes wasm', p: LOCAL_TALLY_WASM }, + { name: 'TallyVotes zkey', p: LOCAL_TALLY_ZKEY } + ]; + const missing = localArtifacts.filter((a) => !fs.existsSync(a.p)); + if (missing.length > 0) { + throw new Error( + `--local specified but local circuit artifacts are missing:\n` + + missing.map((a) => ` ${a.name}: ${a.p}`).join('\n') + + `\nRun "pnpm run circom:build && pnpm run generate-zkeys" in packages/circuits first.` + ); + } + console.log('Using local artifacts for deactivate/msg/tally:'); + console.log(' deactivate wasm:', LOCAL_DEACTIVATE_WASM); + console.log(' deactivate zkey:', LOCAL_DEACTIVATE_ZKEY); + console.log(' msg wasm :', LOCAL_MSG_WASM); + console.log(' msg zkey :', LOCAL_MSG_ZKEY); + console.log(' tally wasm :', LOCAL_TALLY_WASM); + console.log(' tally zkey :', LOCAL_TALLY_ZKEY); +} + +// NOTE: built lazily (not at module load time) because DEACTIVATE_WASM / +// MSG_WASM / TALLY_WASM etc. are only assigned inside ensureArtifacts(), +// which runs well after this module's top-level code. +function getRequiredRemoteArtifacts(): { name: string; p: string }[] { + return [ + { name: 'deactivate.wasm', p: DEACTIVATE_WASM }, + { name: 'deactivate.zkey', p: DEACTIVATE_ZKEY }, + { name: 'msg.wasm', p: MSG_WASM }, + { name: 'msg.zkey', p: MSG_ZKEY }, + { name: 'tally.wasm', p: TALLY_WASM }, + { name: 'tally.zkey', p: TALLY_ZKEY } + ]; +} function ensureRemoteArtifacts(): void { - const missing = REQUIRED_REMOTE_ARTIFACTS.filter((a) => !fs.existsSync(a.p)); + const missing = getRequiredRemoteArtifacts().filter((a) => !fs.existsSync(a.p)); if (missing.length === 0) { console.log('Remote v5 zkey/wasm present at', ZKEYS_V5_BASE); return; @@ -93,14 +147,13 @@ function ensureRemoteArtifacts(): void { } async function ensureArtifacts(): Promise { - fs.mkdirSync(ZKEYS_V5_BASE, { recursive: true }); - // Resolve addkey artifacts if (USE_LOCAL_ADDKEY) { checkLocalAddkeyArtifacts(); ADDKEY_WASM = LOCAL_ADDKEY_WASM; ADDKEY_ZKEY = LOCAL_ADDKEY_ZKEY; } else { + fs.mkdirSync(ZKEYS_V5_BASE, { recursive: true }); const remoteAddkeyWasm = path.join(ZKEYS_V5_BASE, 'add-new-key_2-1-1-5_v5.wasm'); const remoteAddkeyZkey = path.join(ZKEYS_V5_BASE, 'add-new-key_2-1-1-5_v5.zkey'); if (!fs.existsSync(remoteAddkeyWasm) || !fs.existsSync(remoteAddkeyZkey)) { @@ -114,19 +167,39 @@ async function ensureArtifacts(): Promise { ADDKEY_ZKEY = remoteAddkeyZkey; } - // Download and extract remote amaci tar if deactivate/msg/tally are missing. - // The tar extracts directly into BUILD_DIR creating the sub-directory 2-1-1-5/. - const missingRemote = REQUIRED_REMOTE_ARTIFACTS.filter((a) => !fs.existsSync(a.p)); - if (missingRemote.length > 0) { - console.log('Downloading amaci v5 zkeys tar (deactivate/msg/tally)...'); - const tarPath = path.join(BUILD_DIR, 'amaci_2-1-1-5_v5_zkeys.tar.gz'); - await downloadFile(ZKEYS_V5_URLS.amaciZkeysTar, tarPath); - console.log('Extracting amaci zkeys tar...'); - execSync(`tar -xzf "${tarPath}" -C "${BUILD_DIR}"`, { stdio: 'inherit' }); - try { fs.unlinkSync(tarPath); } catch { /* ignore */ } + // Resolve deactivate/msg/tally artifacts + if (USE_LOCAL_ALL) { + checkLocalAllArtifacts(); + DEACTIVATE_WASM = LOCAL_DEACTIVATE_WASM; + DEACTIVATE_ZKEY = LOCAL_DEACTIVATE_ZKEY; + MSG_WASM = LOCAL_MSG_WASM; + MSG_ZKEY = LOCAL_MSG_ZKEY; + TALLY_WASM = LOCAL_TALLY_WASM; + TALLY_ZKEY = LOCAL_TALLY_ZKEY; + } else { + fs.mkdirSync(ZKEYS_V5_BASE, { recursive: true }); + DEACTIVATE_WASM = path.join(ZKEYS_V5_BASE, 'deactivate.wasm'); + DEACTIVATE_ZKEY = path.join(ZKEYS_V5_BASE, 'deactivate.zkey'); + MSG_WASM = path.join(ZKEYS_V5_BASE, 'msg.wasm'); + MSG_ZKEY = path.join(ZKEYS_V5_BASE, 'msg.zkey'); + TALLY_WASM = path.join(ZKEYS_V5_BASE, 'tally.wasm'); + TALLY_ZKEY = path.join(ZKEYS_V5_BASE, 'tally.zkey'); + + // Download and extract remote amaci tar if deactivate/msg/tally are missing. + // The tar extracts directly into BUILD_DIR creating the sub-directory 2-1-1-5/. + const missingRemote = getRequiredRemoteArtifacts().filter((a) => !fs.existsSync(a.p)); + if (missingRemote.length > 0) { + console.log('Downloading amaci v5 zkeys tar (deactivate/msg/tally)...'); + const tarPath = path.join(BUILD_DIR, 'amaci_2-1-1-5_v5_zkeys.tar.gz'); + await downloadFile(ZKEYS_V5_URLS.amaciZkeysTar, tarPath); + console.log('Extracting amaci zkeys tar...'); + execSync(`tar -xzf "${tarPath}" -C "${BUILD_DIR}"`, { stdio: 'inherit' }); + try { fs.unlinkSync(tarPath); } catch { /* ignore */ } + } + + ensureRemoteArtifacts(); } - ensureRemoteArtifacts(); console.log('All artifacts ready.'); } diff --git a/packages/sdk/src/libs/contract/contract.ts b/packages/sdk/src/libs/contract/contract.ts index 809cecd7..e2b4eb08 100644 --- a/packages/sdk/src/libs/contract/contract.ts +++ b/packages/sdk/src/libs/contract/contract.ts @@ -257,6 +257,8 @@ export class Contract { }, voice_credit_mode: params.voiceCreditMode, vote_option_map: params.voteOptionMap, + max_votes_per_option: + params.maxVotesPerOption !== undefined ? params.maxVotesPerOption.toString() : null, voting_time: { start_time: (BigInt(params.startVoting.getTime()) * 1_000_000n).toString(), end_time: (BigInt(params.endVoting.getTime()) * 1_000_000n).toString() diff --git a/packages/sdk/src/libs/contract/types.ts b/packages/sdk/src/libs/contract/types.ts index 73da7cb9..51bc3fd3 100644 --- a/packages/sdk/src/libs/contract/types.ts +++ b/packages/sdk/src/libs/contract/types.ts @@ -23,6 +23,8 @@ export type CreateAMaciRoundParams = { deactivateEnabled: boolean; registrationMode: RegistrationModeConfig; voiceCreditMode: VoiceCreditMode; + /** Per-option vote weight cap enforced by the circuit. Omit or "0" = no limit. */ + maxVotesPerOption?: string | number; fee?: number | StdFee | 'auto'; } & CreateRoundParams; diff --git a/packages/sdk/src/operator.ts b/packages/sdk/src/operator.ts index 5a39ee38..35d72379 100644 --- a/packages/sdk/src/operator.ts +++ b/packages/sdk/src/operator.ts @@ -211,6 +211,8 @@ export class OperatorClient { public voteOptionTreeDepth?: number; public batchSize?: number; public maxVoteOptions?: number; + // Per-option vote weight cap. 0n = no limit (sentinel, matches circuit) + public maxVotesPerOption: bigint = 0n; public voSize?: number; public numSignUps?: number; public isQuadraticCost?: boolean; @@ -829,6 +831,7 @@ export class OperatorClient { voteOptionTreeDepth, batchSize, maxVoteOptions, + maxVotesPerOption = 0n, pollId, isQuadraticCost = false, isAmaci = false, @@ -839,6 +842,7 @@ export class OperatorClient { voteOptionTreeDepth: number; batchSize: number; maxVoteOptions: number; // Required: must match contract's vote options count + maxVotesPerOption?: bigint | number; // Per-option cap, 0 = no limit pollId: number; // Required: poll ID for replay attack prevention isQuadraticCost?: boolean; isAmaci?: boolean; @@ -851,6 +855,14 @@ export class OperatorClient { this.batchSize = batchSize; this.voSize = 5 ** voteOptionTreeDepth; this.maxVoteOptions = maxVoteOptions; + this.maxVotesPerOption = BigInt(maxVotesPerOption); + if (this.maxVotesPerOption < 0n || this.maxVotesPerOption >= 1n << 32n) { + throw new Error('maxVotesPerOption must fit in 32 bits (0 = no limit)'); + } + if (!isAmaci && this.maxVotesPerOption > 0n) { + // Only the AMACI process circuit enforces the per-option cap + throw new Error('maxVotesPerOption is only supported in AMACI mode'); + } this.numSignUps = 0; // Auto-increment on each updateStateTree call this.isQuadraticCost = isQuadraticCost; this.isAmaci = isAmaci; @@ -1466,7 +1478,8 @@ export class OperatorClient { packedVals: BigInt(this.maxVoteOptions!) + (BigInt(this.numSignUps!) << 32n) + - (this.isQuadraticCost ? 1n << 64n : 0n) + (this.isQuadraticCost ? 1n << 64n : 0n) + + (this.maxVotesPerOption << 96n) }, proof: null } as any; @@ -1573,7 +1586,8 @@ export class OperatorClient { const packedVals = BigInt(this.maxVoteOptions!) + (BigInt(this.numSignUps!) << 32n) + - (this.isQuadraticCost ? 1n << 64n : 0n); + (this.isQuadraticCost ? 1n << 64n : 0n) + + (this.maxVotesPerOption << 96n); const batchStartHash = this.messages[batchStartIdx].prevHash; const batchEndHash = this.messages[batchEndIdx - 1].hash; @@ -1720,6 +1734,12 @@ export class OperatorClient { if (!verified) { return 'signature error'; } + // Per-option cap (0n = no limit). Must mirror the circuit's + // validVotesPerOption constraint exactly. + if (this.maxVotesPerOption > 0n && cmd.newVotes > this.maxVotesPerOption) { + return 'votes per option overflow'; + } + const currVotes = s.voTree.leaf(voIdx); if (this.isQuadraticCost) { if (s.balance + currVotes * currVotes < cmd.newVotes * cmd.newVotes) { diff --git a/packages/sdk/src/voter.ts b/packages/sdk/src/voter.ts index 4baef21e..0a52c758 100644 --- a/packages/sdk/src/voter.ts +++ b/packages/sdk/src/voter.ts @@ -241,6 +241,7 @@ export class VoterClient { operatorPubkey, selectedOptions, pollId, + maxVotesPerOption, derivePathParams }: { stateIdx: number; @@ -251,8 +252,25 @@ export class VoterClient { }[]; /** When omitted the legacy message format (no `pollId` in packed element) is used. */ pollId?: bigint | number; + /** + * Optional per-option vote weight cap (round's max_votes_per_option). + * When provided (> 0), votes exceeding the cap fail fast here instead of + * being silently invalidated by the circuit during processing. + */ + maxVotesPerOption?: bigint | number; derivePathParams?: DerivePathParams; }) { + if (maxVotesPerOption !== undefined && BigInt(maxVotesPerOption) > 0n) { + const cap = BigInt(maxVotesPerOption); + for (const option of selectedOptions) { + if (BigInt(option.vc) > cap) { + throw new Error( + `Vote weight ${option.vc} for option ${option.idx} exceeds max votes per option (${cap})` + ); + } + } + } + const plan = this.normalizeVoteOptions(selectedOptions); const payload = From 752c19fe15e799e83a4ab2a539cfbedfa5f9470b Mon Sep 17 00:00:00 2001 From: 99Kies <1290017556@qq.com> Date: Sat, 18 Jul 2026 16:44:53 +0800 Subject: [PATCH 2/6] chore: regenerate cosmwasm ts-codegen clients for max_votes_per_option Regenerate AMaci/Registry/ApiSaas schema JSON and generated TS client/types files (both contracts/*/ts and packages/sdk copies) so the max_votes_per_option field/query added earlier is reflected in the auto-generated bindings. Verified the two generated copies are byte-identical (pre-existing Uint64 number/string discrepancy in Registry.types.ts predates this change) and that packages/sdk builds cleanly (tsc --build + tsup). --- contracts/amaci/schema/cw-amaci.json | 57 +- contracts/amaci/schema/raw/execute.json | 27 - contracts/amaci/schema/raw/instantiate.json | 11 + contracts/amaci/schema/raw/query.json | 13 + .../raw/response_to_max_votes_per_option.json | 6 + contracts/amaci/ts/AMaci.client.ts | 951 ++++++++++------ contracts/amaci/ts/AMaci.types.ts | 480 ++++---- contracts/api-saas/schema/cw-api-saas.json | 11 + contracts/api-saas/schema/raw/execute.json | 11 + contracts/api-saas/ts/ApiSaas.client.ts | 1010 +++++++++++------ contracts/api-saas/ts/ApiSaas.types.ts | 272 +++-- contracts/registry/ts/Registry.client.ts | 727 +++++++----- contracts/registry/ts/Registry.types.ts | 276 +++-- .../sdk/src/libs/contract/ts/AMaci.client.ts | 16 + .../sdk/src/libs/contract/ts/AMaci.types.ts | 21 + .../src/libs/contract/ts/ApiSaas.client.ts | 5 + .../sdk/src/libs/contract/ts/ApiSaas.types.ts | 1 + .../src/libs/contract/ts/Registry.client.ts | 5 + .../src/libs/contract/ts/Registry.types.ts | 1 + 19 files changed, 2405 insertions(+), 1496 deletions(-) create mode 100644 contracts/amaci/schema/raw/response_to_max_votes_per_option.json diff --git a/contracts/amaci/schema/cw-amaci.json b/contracts/amaci/schema/cw-amaci.json index e0410a78..d4b885ae 100644 --- a/contracts/amaci/schema/cw-amaci.json +++ b/contracts/amaci/schema/cw-amaci.json @@ -61,6 +61,17 @@ "fee_recipient": { "$ref": "#/definitions/Addr" }, + "max_votes_per_option": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Uint256" + }, + { + "type": "null" + } + ] + }, "message_delay": { "type": "integer", "format": "uint64", @@ -495,33 +506,6 @@ }, "additionalProperties": false }, - { - "type": "object", - "required": [ - "upload_deactivate_message" - ], - "properties": { - "upload_deactivate_message": { - "type": "object", - "required": [ - "deactivate_message" - ], - "properties": { - "deactivate_message": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/Uint256" - } - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, { "type": "object", "required": [ @@ -1332,6 +1316,19 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "max_votes_per_option" + ], + "properties": { + "max_votes_per_option": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ @@ -2252,6 +2249,12 @@ "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", "type": "string" }, + "max_votes_per_option": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint256", + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + }, "operator": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Addr", diff --git a/contracts/amaci/schema/raw/execute.json b/contracts/amaci/schema/raw/execute.json index ba1f42b2..d7a17ee2 100644 --- a/contracts/amaci/schema/raw/execute.json +++ b/contracts/amaci/schema/raw/execute.json @@ -143,33 +143,6 @@ }, "additionalProperties": false }, - { - "type": "object", - "required": [ - "upload_deactivate_message" - ], - "properties": { - "upload_deactivate_message": { - "type": "object", - "required": [ - "deactivate_message" - ], - "properties": { - "deactivate_message": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/Uint256" - } - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, { "type": "object", "required": [ diff --git a/contracts/amaci/schema/raw/instantiate.json b/contracts/amaci/schema/raw/instantiate.json index 2c11e590..5ab9d1ee 100644 --- a/contracts/amaci/schema/raw/instantiate.json +++ b/contracts/amaci/schema/raw/instantiate.json @@ -57,6 +57,17 @@ "fee_recipient": { "$ref": "#/definitions/Addr" }, + "max_votes_per_option": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Uint256" + }, + { + "type": "null" + } + ] + }, "message_delay": { "type": "integer", "format": "uint64", diff --git a/contracts/amaci/schema/raw/query.json b/contracts/amaci/schema/raw/query.json index 84702336..61f8b8c0 100644 --- a/contracts/amaci/schema/raw/query.json +++ b/contracts/amaci/schema/raw/query.json @@ -307,6 +307,19 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "max_votes_per_option" + ], + "properties": { + "max_votes_per_option": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/amaci/schema/raw/response_to_max_votes_per_option.json b/contracts/amaci/schema/raw/response_to_max_votes_per_option.json new file mode 100644 index 00000000..9534e6a6 --- /dev/null +++ b/contracts/amaci/schema/raw/response_to_max_votes_per_option.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint256", + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" +} diff --git a/contracts/amaci/ts/AMaci.client.ts b/contracts/amaci/ts/AMaci.client.ts index 1aceae74..9c8f45b8 100644 --- a/contracts/amaci/ts/AMaci.client.ts +++ b/contracts/amaci/ts/AMaci.client.ts @@ -1,12 +1,50 @@ /** -* This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ + * This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { Coin, StdFee } from "@cosmjs/amino"; -import { Addr, Uint256, Uint128, RegistrationModeConfig, VoiceCreditMode, Timestamp, Uint64, InstantiateMsg, PubKey, MaciParameters, WhitelistBase, WhitelistBaseConfig, RoundInfo, VotingTime, ExecuteMsg, RegistrationConfigUpdate, MessageData, Groth16ProofType, QueryMsg, ArrayOfUint256, Boolean, DelayConfigResponse, DelayType, DelayRecords, DelayRecord, FeeConfigResponse, PeriodStatus, Period, RegistrationMode, RegistrationConfigInfo, TallyDelayInfo, NullableString, NullableUint256, RegistrationStatus, ArrayOfString } from "./AMaci.types"; +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'; +import { Coin, StdFee } from '@cosmjs/amino'; +import { + Addr, + Uint256, + Uint128, + RegistrationModeConfig, + VoiceCreditMode, + Timestamp, + Uint64, + InstantiateMsg, + PubKey, + MaciParameters, + WhitelistBase, + WhitelistBaseConfig, + RoundInfo, + VotingTime, + ExecuteMsg, + RegistrationConfigUpdate, + MessageData, + Groth16ProofType, + QueryMsg, + ArrayOfUint256, + Boolean, + DelayConfigResponse, + DelayType, + DelayRecords, + DelayRecord, + FeeConfigResponse, + PeriodStatus, + Period, + RegistrationMode, + RegistrationConfigInfo, + TallyDelayInfo, + VkeysResponse, + Groth16VkeyStr, + NullableString, + NullableUint256, + RegistrationStatus, + ArrayOfString +} from './AMaci.types'; export interface AMaciReadOnlyInterface { contractAddress: string; admin: () => Promise; @@ -21,31 +59,16 @@ export interface AMaciReadOnlyInterface { getProcessedMsgCount: () => Promise; getProcessedUserCount: () => Promise; getStateTreeRoot: () => Promise; - getNode: ({ - index - }: { - index: Uint256; - }) => Promise; - getResult: ({ - index - }: { - index: Uint256; - }) => Promise; + getNode: ({ index }: { index: Uint256 }) => Promise; + getResult: ({ index }: { index: Uint256 }) => Promise; getAllResult: () => Promise; getAllResults: () => Promise; - getVoiceCreditBalance: ({ - index - }: { - index: Uint256; - }) => Promise; + getVoiceCreditBalance: ({ index }: { index: Uint256 }) => Promise; getVoiceCreditAmount: () => Promise; - signuped: ({ - pubkey - }: { - pubkey: PubKey; - }) => Promise; + signuped: ({ pubkey }: { pubkey: PubKey }) => Promise; voteOptionMap: () => Promise; maxVoteOptions: () => Promise; + maxVotesPerOption: () => Promise; queryCircuitType: () => Promise; queryCertSystem: () => Promise; queryPreDeactivateRoot: () => Promise; @@ -55,11 +78,7 @@ export interface AMaciReadOnlyInterface { queryOracleWhitelistConfig: () => Promise; queryCurrentStateCommitment: () => Promise; getCoordinatorHash: () => Promise; - getMsgHash: ({ - index - }: { - index: Uint256; - }) => Promise; + getMsgHash: ({ index }: { index: Uint256 }) => Promise; getCurrentDeactivateCommitment: () => Promise; getPollId: () => Promise; getDeactivateEnabled: () => Promise; @@ -77,6 +96,7 @@ export interface AMaciReadOnlyInterface { }) => Promise; getFeeConfig: () => Promise; getDelayConfig: () => Promise; + getVkeys: () => Promise; } export class AMaciQueryClient implements AMaciReadOnlyInterface { client: CosmWasmClient; @@ -105,6 +125,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { this.signuped = this.signuped.bind(this); this.voteOptionMap = this.voteOptionMap.bind(this); this.maxVoteOptions = this.maxVoteOptions.bind(this); + this.maxVotesPerOption = this.maxVotesPerOption.bind(this); this.queryCircuitType = this.queryCircuitType.bind(this); this.queryCertSystem = this.queryCertSystem.bind(this); this.queryPreDeactivateRoot = this.queryPreDeactivateRoot.bind(this); @@ -122,6 +143,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { this.queryRegistrationStatus = this.queryRegistrationStatus.bind(this); this.getFeeConfig = this.getFeeConfig.bind(this); this.getDelayConfig = this.getDelayConfig.bind(this); + this.getVkeys = this.getVkeys.bind(this); } admin = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { @@ -183,22 +205,14 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { get_state_tree_root: {} }); }; - getNode = async ({ - index - }: { - index: Uint256; - }): Promise => { + getNode = async ({ index }: { index: Uint256 }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_node: { index } }); }; - getResult = async ({ - index - }: { - index: Uint256; - }): Promise => { + getResult = async ({ index }: { index: Uint256 }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_result: { index @@ -215,11 +229,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { get_all_results: {} }); }; - getVoiceCreditBalance = async ({ - index - }: { - index: Uint256; - }): Promise => { + getVoiceCreditBalance = async ({ index }: { index: Uint256 }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_voice_credit_balance: { index @@ -231,11 +241,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { get_voice_credit_amount: {} }); }; - signuped = async ({ - pubkey - }: { - pubkey: PubKey; - }): Promise => { + signuped = async ({ pubkey }: { pubkey: PubKey }): Promise => { return this.client.queryContractSmart(this.contractAddress, { signuped: { pubkey @@ -252,6 +258,11 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { max_vote_options: {} }); }; + maxVotesPerOption = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + max_votes_per_option: {} + }); + }; queryCircuitType = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { query_circuit_type: {} @@ -297,11 +308,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { get_coordinator_hash: {} }); }; - getMsgHash = async ({ - index - }: { - index: Uint256; - }): Promise => { + getMsgHash = async ({ index }: { index: Uint256 }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_msg_hash: { index @@ -358,105 +365,178 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { get_delay_config: {} }); }; + getVkeys = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_vkeys: {} + }); + }; } export interface AMaciInterface extends AMaciReadOnlyInterface { contractAddress: string; sender: string; - setRoundInfo: ({ - roundInfo - }: { - roundInfo: RoundInfo; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateRegistrationConfig: ({ - config - }: { - config: RegistrationConfigUpdate; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setVoteOptionsMap: ({ - voteOptionMap - }: { - voteOptionMap: string[]; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - signUp: ({ - amount, - certificate, - pubkey - }: { - amount?: Uint256; - certificate?: string; - pubkey: PubKey; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - startProcessPeriod: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - publishDeactivateMessage: ({ - encPubKey, - message - }: { - encPubKey: PubKey; - message: MessageData; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - processDeactivateMessage: ({ - groth16Proof, - newDeactivateCommitment, - newDeactivateRoot, - size - }: { - groth16Proof: Groth16ProofType; - newDeactivateCommitment: Uint256; - newDeactivateRoot: Uint256; - size: Uint256; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - addNewKey: ({ - d, - groth16Proof, - nullifier, - pubkey - }: { - d: Uint256[]; - groth16Proof: Groth16ProofType; - nullifier: Uint256; - pubkey: PubKey; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - preAddNewKey: ({ - d, - groth16Proof, - nullifier, - pubkey - }: { - d: Uint256[]; - groth16Proof: Groth16ProofType; - nullifier: Uint256; - pubkey: PubKey; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - publishMessage: ({ - encPubKeys, - messages - }: { - encPubKeys: PubKey[]; - messages: MessageData[]; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - processMessage: ({ - groth16Proof, - newStateCommitment - }: { - groth16Proof: Groth16ProofType; - newStateCommitment: Uint256; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - stopProcessingPeriod: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - processTally: ({ - groth16Proof, - newTallyCommitment - }: { - groth16Proof: Groth16ProofType; - newTallyCommitment: Uint256; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - stopTallyingPeriod: ({ - results, - salt - }: { - results: Uint256[]; - salt: Uint256; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - claim: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setRoundInfo: ( + { + roundInfo + }: { + roundInfo: RoundInfo; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + updateRegistrationConfig: ( + { + config + }: { + config: RegistrationConfigUpdate; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + setVoteOptionsMap: ( + { + voteOptionMap + }: { + voteOptionMap: string[]; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + signUp: ( + { + amount, + certificate, + pubkey + }: { + amount?: Uint256; + certificate?: string; + pubkey: PubKey; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + startProcessPeriod: ( + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + publishDeactivateMessage: ( + { + encPubKey, + message + }: { + encPubKey: PubKey; + message: MessageData; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + processDeactivateMessage: ( + { + groth16Proof, + newDeactivateCommitment, + newDeactivateRoot, + size + }: { + groth16Proof: Groth16ProofType; + newDeactivateCommitment: Uint256; + newDeactivateRoot: Uint256; + size: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + addNewKey: ( + { + d, + groth16Proof, + nullifier, + pubkey + }: { + d: Uint256[]; + groth16Proof: Groth16ProofType; + nullifier: Uint256; + pubkey: PubKey; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + preAddNewKey: ( + { + d, + groth16Proof, + nullifier, + pubkey + }: { + d: Uint256[]; + groth16Proof: Groth16ProofType; + nullifier: Uint256; + pubkey: PubKey; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + publishMessage: ( + { + encPubKeys, + messages + }: { + encPubKeys: PubKey[]; + messages: MessageData[]; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + processMessage: ( + { + groth16Proof, + newStateCommitment + }: { + groth16Proof: Groth16ProofType; + newStateCommitment: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + stopProcessingPeriod: ( + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + processTally: ( + { + groth16Proof, + newTallyCommitment + }: { + groth16Proof: Groth16ProofType; + newTallyCommitment: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + stopTallyingPeriod: ( + { + results, + salt + }: { + results: Uint256[]; + salt: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + claim: (fee?: number | StdFee | 'auto', memo?: string, _funds?: Coin[]) => Promise; } export class AMaciClient extends AMaciQueryClient implements AMaciInterface { client: SigningCosmWasmClient; @@ -483,199 +563,376 @@ export class AMaciClient extends AMaciQueryClient implements AMaciInterface { this.stopTallyingPeriod = this.stopTallyingPeriod.bind(this); this.claim = this.claim.bind(this); } - setRoundInfo = async ({ - roundInfo - }: { - roundInfo: RoundInfo; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_round_info: { - round_info: roundInfo - } - }, fee, memo, _funds); - }; - updateRegistrationConfig = async ({ - config - }: { - config: RegistrationConfigUpdate; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_registration_config: { - config - } - }, fee, memo, _funds); - }; - setVoteOptionsMap = async ({ - voteOptionMap - }: { - voteOptionMap: string[]; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_vote_options_map: { - vote_option_map: voteOptionMap - } - }, fee, memo, _funds); + setRoundInfo = async ( + { + roundInfo + }: { + roundInfo: RoundInfo; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_round_info: { + round_info: roundInfo + } + }, + fee, + memo, + _funds + ); + }; + updateRegistrationConfig = async ( + { + config + }: { + config: RegistrationConfigUpdate; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_registration_config: { + config + } + }, + fee, + memo, + _funds + ); + }; + setVoteOptionsMap = async ( + { + voteOptionMap + }: { + voteOptionMap: string[]; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_vote_options_map: { + vote_option_map: voteOptionMap + } + }, + fee, + memo, + _funds + ); + }; + signUp = async ( + { + amount, + certificate, + pubkey + }: { + amount?: Uint256; + certificate?: string; + pubkey: PubKey; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + sign_up: { + amount, + certificate, + pubkey + } + }, + fee, + memo, + _funds + ); + }; + startProcessPeriod = async ( + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + start_process_period: {} + }, + fee, + memo, + _funds + ); + }; + publishDeactivateMessage = async ( + { + encPubKey, + message + }: { + encPubKey: PubKey; + message: MessageData; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + publish_deactivate_message: { + enc_pub_key: encPubKey, + message + } + }, + fee, + memo, + _funds + ); + }; + processDeactivateMessage = async ( + { + groth16Proof, + newDeactivateCommitment, + newDeactivateRoot, + size + }: { + groth16Proof: Groth16ProofType; + newDeactivateCommitment: Uint256; + newDeactivateRoot: Uint256; + size: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + process_deactivate_message: { + groth16_proof: groth16Proof, + new_deactivate_commitment: newDeactivateCommitment, + new_deactivate_root: newDeactivateRoot, + size + } + }, + fee, + memo, + _funds + ); + }; + addNewKey = async ( + { + d, + groth16Proof, + nullifier, + pubkey + }: { + d: Uint256[]; + groth16Proof: Groth16ProofType; + nullifier: Uint256; + pubkey: PubKey; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + add_new_key: { + d, + groth16_proof: groth16Proof, + nullifier, + pubkey + } + }, + fee, + memo, + _funds + ); + }; + preAddNewKey = async ( + { + d, + groth16Proof, + nullifier, + pubkey + }: { + d: Uint256[]; + groth16Proof: Groth16ProofType; + nullifier: Uint256; + pubkey: PubKey; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + pre_add_new_key: { + d, + groth16_proof: groth16Proof, + nullifier, + pubkey + } + }, + fee, + memo, + _funds + ); + }; + publishMessage = async ( + { + encPubKeys, + messages + }: { + encPubKeys: PubKey[]; + messages: MessageData[]; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + publish_message: { + enc_pub_keys: encPubKeys, + messages + } + }, + fee, + memo, + _funds + ); + }; + processMessage = async ( + { + groth16Proof, + newStateCommitment + }: { + groth16Proof: Groth16ProofType; + newStateCommitment: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + process_message: { + groth16_proof: groth16Proof, + new_state_commitment: newStateCommitment + } + }, + fee, + memo, + _funds + ); + }; + stopProcessingPeriod = async ( + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + stop_processing_period: {} + }, + fee, + memo, + _funds + ); + }; + processTally = async ( + { + groth16Proof, + newTallyCommitment + }: { + groth16Proof: Groth16ProofType; + newTallyCommitment: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + process_tally: { + groth16_proof: groth16Proof, + new_tally_commitment: newTallyCommitment + } + }, + fee, + memo, + _funds + ); + }; + stopTallyingPeriod = async ( + { + results, + salt + }: { + results: Uint256[]; + salt: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + stop_tallying_period: { + results, + salt + } + }, + fee, + memo, + _funds + ); + }; + claim = async ( + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + claim: {} + }, + fee, + memo, + _funds + ); }; - signUp = async ({ - amount, - certificate, - pubkey - }: { - amount?: Uint256; - certificate?: string; - pubkey: PubKey; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - sign_up: { - amount, - certificate, - pubkey - } - }, fee, memo, _funds); - }; - startProcessPeriod = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - start_process_period: {} - }, fee, memo, _funds); - }; - publishDeactivateMessage = async ({ - encPubKey, - message - }: { - encPubKey: PubKey; - message: MessageData; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - publish_deactivate_message: { - enc_pub_key: encPubKey, - message - } - }, fee, memo, _funds); - }; - processDeactivateMessage = async ({ - groth16Proof, - newDeactivateCommitment, - newDeactivateRoot, - size - }: { - groth16Proof: Groth16ProofType; - newDeactivateCommitment: Uint256; - newDeactivateRoot: Uint256; - size: Uint256; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - process_deactivate_message: { - groth16_proof: groth16Proof, - new_deactivate_commitment: newDeactivateCommitment, - new_deactivate_root: newDeactivateRoot, - size - } - }, fee, memo, _funds); - }; - addNewKey = async ({ - d, - groth16Proof, - nullifier, - pubkey - }: { - d: Uint256[]; - groth16Proof: Groth16ProofType; - nullifier: Uint256; - pubkey: PubKey; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - add_new_key: { - d, - groth16_proof: groth16Proof, - nullifier, - pubkey - } - }, fee, memo, _funds); - }; - preAddNewKey = async ({ - d, - groth16Proof, - nullifier, - pubkey - }: { - d: Uint256[]; - groth16Proof: Groth16ProofType; - nullifier: Uint256; - pubkey: PubKey; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - pre_add_new_key: { - d, - groth16_proof: groth16Proof, - nullifier, - pubkey - } - }, fee, memo, _funds); - }; - publishMessage = async ({ - encPubKeys, - messages - }: { - encPubKeys: PubKey[]; - messages: MessageData[]; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - publish_message: { - enc_pub_keys: encPubKeys, - messages - } - }, fee, memo, _funds); - }; - processMessage = async ({ - groth16Proof, - newStateCommitment - }: { - groth16Proof: Groth16ProofType; - newStateCommitment: Uint256; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - process_message: { - groth16_proof: groth16Proof, - new_state_commitment: newStateCommitment - } - }, fee, memo, _funds); - }; - stopProcessingPeriod = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - stop_processing_period: {} - }, fee, memo, _funds); - }; - processTally = async ({ - groth16Proof, - newTallyCommitment - }: { - groth16Proof: Groth16ProofType; - newTallyCommitment: Uint256; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - process_tally: { - groth16_proof: groth16Proof, - new_tally_commitment: newTallyCommitment - } - }, fee, memo, _funds); - }; - stopTallyingPeriod = async ({ - results, - salt - }: { - results: Uint256[]; - salt: Uint256; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - stop_tallying_period: { - results, - salt - } - }, fee, memo, _funds); - }; - claim = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - claim: {} - }, fee, memo, _funds); - }; -} \ No newline at end of file +} diff --git a/contracts/amaci/ts/AMaci.types.ts b/contracts/amaci/ts/AMaci.types.ts index 90ce36c9..50a78038 100644 --- a/contracts/amaci/ts/AMaci.types.ts +++ b/contracts/amaci/ts/AMaci.types.ts @@ -1,31 +1,36 @@ /** -* This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ + * This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ export type Addr = string; export type Uint256 = string; export type Uint128 = string; -export type RegistrationModeConfig = { - sign_up_with_static_whitelist: { - whitelist: WhitelistBase; - }; -} | { - sign_up_with_oracle: { - oracle_pubkey: string; - }; -} | { - pre_populated: { - pre_deactivate_coordinator: PubKey; - pre_deactivate_root: Uint256; - }; -}; -export type VoiceCreditMode = "dynamic" | { - unified: { - amount: Uint256; - }; -}; +export type RegistrationModeConfig = + | { + sign_up_with_static_whitelist: { + whitelist: WhitelistBase; + }; + } + | { + sign_up_with_oracle: { + oracle_pubkey: string; + }; + } + | { + pre_populated: { + pre_deactivate_coordinator: PubKey; + pre_deactivate_root: Uint256; + }; + }; +export type VoiceCreditMode = + | 'dynamic' + | { + unified: { + amount: Uint256; + }; + }; export type Timestamp = Uint64; export type Uint64 = string; export interface InstantiateMsg { @@ -38,6 +43,7 @@ export interface InstantiateMsg { deactivate_enabled: boolean; deactivate_fee: Uint128; fee_recipient: Addr; + max_votes_per_option?: Uint256 | null; message_delay: number; message_fee: Uint128; operator: Addr; @@ -77,77 +83,92 @@ export interface VotingTime { end_time: Timestamp; start_time: Timestamp; } -export type ExecuteMsg = { - set_round_info: { - round_info: RoundInfo; - }; -} | { - update_registration_config: { - config: RegistrationConfigUpdate; - }; -} | { - set_vote_options_map: { - vote_option_map: string[]; - }; -} | { - sign_up: { - amount?: Uint256 | null; - certificate?: string | null; - pubkey: PubKey; - }; -} | { - start_process_period: {}; -} | { - publish_deactivate_message: { - enc_pub_key: PubKey; - message: MessageData; - }; -} | { - process_deactivate_message: { - groth16_proof: Groth16ProofType; - new_deactivate_commitment: Uint256; - new_deactivate_root: Uint256; - size: Uint256; - }; -} | { - add_new_key: { - d: [Uint256, Uint256, Uint256, Uint256]; - groth16_proof: Groth16ProofType; - nullifier: Uint256; - pubkey: PubKey; - }; -} | { - pre_add_new_key: { - d: [Uint256, Uint256, Uint256, Uint256]; - groth16_proof: Groth16ProofType; - nullifier: Uint256; - pubkey: PubKey; - }; -} | { - publish_message: { - enc_pub_keys: PubKey[]; - messages: MessageData[]; - }; -} | { - process_message: { - groth16_proof: Groth16ProofType; - new_state_commitment: Uint256; - }; -} | { - stop_processing_period: {}; -} | { - process_tally: { - groth16_proof: Groth16ProofType; - new_tally_commitment: Uint256; - }; -} | { - stop_tallying_period: { - results: Uint256[]; - salt: Uint256; - }; -} | { - claim: {}; -}; +export type ExecuteMsg = + | { + set_round_info: { + round_info: RoundInfo; + }; + } + | { + update_registration_config: { + config: RegistrationConfigUpdate; + }; + } + | { + set_vote_options_map: { + vote_option_map: string[]; + }; + } + | { + sign_up: { + amount?: Uint256 | null; + certificate?: string | null; + pubkey: PubKey; + }; + } + | { + start_process_period: {}; + } + | { + publish_deactivate_message: { + enc_pub_key: PubKey; + message: MessageData; + }; + } + | { + process_deactivate_message: { + groth16_proof: Groth16ProofType; + new_deactivate_commitment: Uint256; + new_deactivate_root: Uint256; + size: Uint256; + }; + } + | { + add_new_key: { + d: [Uint256, Uint256, Uint256, Uint256]; + groth16_proof: Groth16ProofType; + nullifier: Uint256; + pubkey: PubKey; + }; + } + | { + pre_add_new_key: { + d: [Uint256, Uint256, Uint256, Uint256]; + groth16_proof: Groth16ProofType; + nullifier: Uint256; + pubkey: PubKey; + }; + } + | { + publish_message: { + enc_pub_keys: PubKey[]; + messages: MessageData[]; + }; + } + | { + process_message: { + groth16_proof: Groth16ProofType; + new_state_commitment: Uint256; + }; + } + | { + stop_processing_period: {}; + } + | { + process_tally: { + groth16_proof: Groth16ProofType; + new_tally_commitment: Uint256; + }; + } + | { + stop_tallying_period: { + results: Uint256[]; + salt: Uint256; + }; + } + | { + claim: {}; + }; export interface RegistrationConfigUpdate { deactivate_enabled?: boolean | null; registration_mode?: RegistrationModeConfig | null; @@ -161,98 +182,142 @@ export interface Groth16ProofType { b: string; c: string; } -export type QueryMsg = { - admin: {}; -} | { - operator: {}; -} | { - get_round_info: {}; -} | { - get_voting_time: {}; -} | { - get_period: {}; -} | { - get_num_sign_up: {}; -} | { - get_msg_chain_length: {}; -} | { - get_d_msg_chain_length: {}; -} | { - get_processed_d_msg_count: {}; -} | { - get_processed_msg_count: {}; -} | { - get_processed_user_count: {}; -} | { - get_state_tree_root: {}; -} | { - get_node: { - index: Uint256; - }; -} | { - get_result: { - index: Uint256; - }; -} | { - get_all_result: {}; -} | { - get_all_results: {}; -} | { - get_voice_credit_balance: { - index: Uint256; - }; -} | { - get_voice_credit_amount: {}; -} | { - signuped: { - pubkey: PubKey; - }; -} | { - vote_option_map: {}; -} | { - max_vote_options: {}; -} | { - query_circuit_type: {}; -} | { - query_cert_system: {}; -} | { - query_pre_deactivate_root: {}; -} | { - query_pre_deactivate_coordinator_hash: {}; -} | { - get_delay_records: {}; -} | { - get_tally_delay: {}; -} | { - query_oracle_whitelist_config: {}; -} | { - query_current_state_commitment: {}; -} | { - get_coordinator_hash: {}; -} | { - get_msg_hash: { - index: Uint256; - }; -} | { - get_current_deactivate_commitment: {}; -} | { - get_poll_id: {}; -} | { - get_deactivate_enabled: {}; -} | { - get_registration_config: {}; -} | { - query_registration_status: { - amount?: Uint256 | null; - certificate?: string | null; - pubkey?: PubKey | null; - sender?: Addr | null; - }; -} | { - get_fee_config: {}; -} | { - get_delay_config: {}; -}; +export type QueryMsg = + | { + admin: {}; + } + | { + operator: {}; + } + | { + get_round_info: {}; + } + | { + get_voting_time: {}; + } + | { + get_period: {}; + } + | { + get_num_sign_up: {}; + } + | { + get_msg_chain_length: {}; + } + | { + get_d_msg_chain_length: {}; + } + | { + get_processed_d_msg_count: {}; + } + | { + get_processed_msg_count: {}; + } + | { + get_processed_user_count: {}; + } + | { + get_state_tree_root: {}; + } + | { + get_node: { + index: Uint256; + }; + } + | { + get_result: { + index: Uint256; + }; + } + | { + get_all_result: {}; + } + | { + get_all_results: {}; + } + | { + get_voice_credit_balance: { + index: Uint256; + }; + } + | { + get_voice_credit_amount: {}; + } + | { + signuped: { + pubkey: PubKey; + }; + } + | { + vote_option_map: {}; + } + | { + max_vote_options: {}; + } + | { + max_votes_per_option: {}; + } + | { + query_circuit_type: {}; + } + | { + query_cert_system: {}; + } + | { + query_pre_deactivate_root: {}; + } + | { + query_pre_deactivate_coordinator_hash: {}; + } + | { + get_delay_records: {}; + } + | { + get_tally_delay: {}; + } + | { + query_oracle_whitelist_config: {}; + } + | { + query_current_state_commitment: {}; + } + | { + get_coordinator_hash: {}; + } + | { + get_msg_hash: { + index: Uint256; + }; + } + | { + get_current_deactivate_commitment: {}; + } + | { + get_poll_id: {}; + } + | { + get_deactivate_enabled: {}; + } + | { + get_registration_config: {}; + } + | { + query_registration_status: { + amount?: Uint256 | null; + certificate?: string | null; + pubkey?: PubKey | null; + sender?: Addr | null; + }; + } + | { + get_fee_config: {}; + } + | { + get_delay_config: {}; + } + | { + get_vkeys: {}; + }; export type ArrayOfUint256 = Uint256[]; export type Boolean = boolean; export interface DelayConfigResponse { @@ -261,7 +326,7 @@ export interface DelayConfigResponse { message_delay: number; signup_delay: number; } -export type DelayType = "deactivate_delay" | "tally_delay"; +export type DelayType = 'deactivate_delay' | 'tally_delay'; export interface DelayRecords { records: DelayRecord[]; } @@ -277,20 +342,23 @@ export interface FeeConfigResponse { message_fee: Uint128; signup_fee: Uint128; } -export type PeriodStatus = "pending" | "processing" | "tallying" | "ended"; +export type PeriodStatus = 'pending' | 'processing' | 'tallying' | 'ended'; export interface Period { status: PeriodStatus; } -export type RegistrationMode = "sign_up_with_static_whitelist" | { - sign_up_with_oracle: { - oracle_pubkey: string; - }; -} | { - pre_populated: { - pre_deactivate_coordinator: PubKey; - pre_deactivate_root: Uint256; - }; -}; +export type RegistrationMode = + | 'sign_up_with_static_whitelist' + | { + sign_up_with_oracle: { + oracle_pubkey: string; + }; + } + | { + pre_populated: { + pre_deactivate_coordinator: PubKey; + pre_deactivate_root: Uint256; + }; + }; export interface RegistrationConfigInfo { deactivate_enabled: boolean; registration_mode: RegistrationMode; @@ -303,6 +371,20 @@ export interface TallyDelayInfo { num_sign_ups: Uint256; total_work: number; } +export interface VkeysResponse { + add_key_vkey: Groth16VkeyStr; + deactivate_vkey: Groth16VkeyStr; + process_vkey: Groth16VkeyStr; + tally_vkey: Groth16VkeyStr; +} +export interface Groth16VkeyStr { + alpha_1: number[]; + beta_2: number[]; + delta_2: number[]; + gamma_2: number[]; + ic0: number[]; + ic1: number[]; +} export type NullableString = string | null; export type NullableUint256 = Uint256 | null; export interface RegistrationStatus { @@ -310,4 +392,4 @@ export interface RegistrationStatus { can_sign_up: boolean; is_register: boolean; } -export type ArrayOfString = string[]; \ No newline at end of file +export type ArrayOfString = string[]; diff --git a/contracts/api-saas/schema/cw-api-saas.json b/contracts/api-saas/schema/cw-api-saas.json index 10c49451..84f889dc 100644 --- a/contracts/api-saas/schema/cw-api-saas.json +++ b/contracts/api-saas/schema/cw-api-saas.json @@ -205,6 +205,17 @@ "deactivate_enabled": { "type": "boolean" }, + "max_votes_per_option": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Uint256" + }, + { + "type": "null" + } + ] + }, "operator": { "$ref": "#/definitions/Addr" }, diff --git a/contracts/api-saas/schema/raw/execute.json b/contracts/api-saas/schema/raw/execute.json index a6b14c25..abc91588 100644 --- a/contracts/api-saas/schema/raw/execute.json +++ b/contracts/api-saas/schema/raw/execute.json @@ -169,6 +169,17 @@ "deactivate_enabled": { "type": "boolean" }, + "max_votes_per_option": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Uint256" + }, + { + "type": "null" + } + ] + }, "operator": { "$ref": "#/definitions/Addr" }, diff --git a/contracts/api-saas/ts/ApiSaas.client.ts b/contracts/api-saas/ts/ApiSaas.client.ts index ad8983f4..370ec0ce 100644 --- a/contracts/api-saas/ts/ApiSaas.client.ts +++ b/contracts/api-saas/ts/ApiSaas.client.ts @@ -1,21 +1,41 @@ /** -* This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ + * This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { Coin, StdFee } from "@cosmjs/amino"; -import { Addr, InstantiateMsg, ExecuteMsg, Uint128, Uint256, RegistrationModeConfig, VoiceCreditMode, Timestamp, Uint64, WhitelistBase, WhitelistBaseConfig, PubKey, RoundInfo, VotingTime, SaasFeeConfig, EncPubKeyParam, MessageDataParam, Groth16ProofParam, QueryMsg, Config, Boolean, ArrayOfOperatorInfo, OperatorInfo } from "./ApiSaas.types"; +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'; +import { Coin, StdFee } from '@cosmjs/amino'; +import { + Addr, + InstantiateMsg, + ExecuteMsg, + Uint128, + Uint256, + RegistrationModeConfig, + VoiceCreditMode, + Timestamp, + Uint64, + WhitelistBase, + WhitelistBaseConfig, + PubKey, + RoundInfo, + VotingTime, + SaasFeeConfig, + EncPubKeyParam, + MessageDataParam, + Groth16ProofParam, + QueryMsg, + Config, + Boolean, + ArrayOfOperatorInfo, + OperatorInfo +} from './ApiSaas.types'; export interface ApiSaasReadOnlyInterface { contractAddress: string; config: () => Promise; operators: () => Promise; - isOperator: ({ - address - }: { - address: Addr; - }) => Promise; + isOperator: ({ address }: { address: Addr }) => Promise; balance: () => Promise; treasuryManager: () => Promise; } @@ -41,11 +61,7 @@ export class ApiSaasQueryClient implements ApiSaasReadOnlyInterface { operators: {} }); }; - isOperator = async ({ - address - }: { - address: Addr; - }): Promise => { + isOperator = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { is_operator: { address @@ -66,131 +82,207 @@ export class ApiSaasQueryClient implements ApiSaasReadOnlyInterface { export interface ApiSaasInterface extends ApiSaasReadOnlyInterface { contractAddress: string; sender: string; - updateConfig: ({ - admin, - denom - }: { - admin?: Addr; - denom?: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateAmaciRegistryContract: ({ - registryContract - }: { - registryContract: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - addOperator: ({ - operator - }: { - operator: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - removeOperator: ({ - operator - }: { - operator: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - deposit: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - withdraw: ({ - amount, - recipient - }: { - amount: Uint128; - recipient?: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - createAmaciRound: ({ - certificationSystem, - circuitType, - deactivateEnabled, - operator, - registrationMode, - roundInfo, - voiceCreditMode, - voteOptionMap, - votingTime - }: { - certificationSystem: Uint256; - circuitType: Uint256; - deactivateEnabled: boolean; - operator: Addr; - registrationMode: RegistrationModeConfig; - roundInfo: RoundInfo; - voiceCreditMode: VoiceCreditMode; - voteOptionMap: string[]; - votingTime: VotingTime; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateFeeConfig: ({ - config - }: { - config: SaasFeeConfig; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setRoundInfo: ({ - contractAddr, - roundInfo - }: { - contractAddr: string; - roundInfo: RoundInfo; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setVoteOptionsMap: ({ - contractAddr, - voteOptionMap - }: { - contractAddr: string; - voteOptionMap: string[]; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - publishMessage: ({ - contractAddr, - encPubKeys, - messages - }: { - contractAddr: string; - encPubKeys: EncPubKeyParam[]; - messages: MessageDataParam[]; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - publishDeactivateMessage: ({ - contractAddr, - encPubKey, - message - }: { - contractAddr: string; - encPubKey: EncPubKeyParam; - message: MessageDataParam; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - signUp: ({ - amount, - certificate, - contractAddr, - pubkey - }: { - amount?: string; - certificate?: string; - contractAddr: string; - pubkey: EncPubKeyParam; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - addNewKey: ({ - contractAddr, - d, - groth16Proof, - nullifier, - pubkey - }: { - contractAddr: string; - d: string[]; - groth16Proof: Groth16ProofParam; - nullifier: string; - pubkey: EncPubKeyParam; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - preAddNewKey: ({ - contractAddr, - d, - groth16Proof, - nullifier, - pubkey - }: { - contractAddr: string; - d: string[]; - groth16Proof: Groth16ProofParam; - nullifier: string; - pubkey: EncPubKeyParam; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateConfig: ( + { + admin, + denom + }: { + admin?: Addr; + denom?: string; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + updateAmaciRegistryContract: ( + { + registryContract + }: { + registryContract: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + addOperator: ( + { + operator + }: { + operator: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + removeOperator: ( + { + operator + }: { + operator: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + deposit: ( + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + withdraw: ( + { + amount, + recipient + }: { + amount: Uint128; + recipient?: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + createAmaciRound: ( + { + certificationSystem, + circuitType, + deactivateEnabled, + maxVotesPerOption, + operator, + registrationMode, + roundInfo, + voiceCreditMode, + voteOptionMap, + votingTime + }: { + certificationSystem: Uint256; + circuitType: Uint256; + deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; + operator: Addr; + registrationMode: RegistrationModeConfig; + roundInfo: RoundInfo; + voiceCreditMode: VoiceCreditMode; + voteOptionMap: string[]; + votingTime: VotingTime; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + updateFeeConfig: ( + { + config + }: { + config: SaasFeeConfig; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + setRoundInfo: ( + { + contractAddr, + roundInfo + }: { + contractAddr: string; + roundInfo: RoundInfo; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + setVoteOptionsMap: ( + { + contractAddr, + voteOptionMap + }: { + contractAddr: string; + voteOptionMap: string[]; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + publishMessage: ( + { + contractAddr, + encPubKeys, + messages + }: { + contractAddr: string; + encPubKeys: EncPubKeyParam[]; + messages: MessageDataParam[]; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + publishDeactivateMessage: ( + { + contractAddr, + encPubKey, + message + }: { + contractAddr: string; + encPubKey: EncPubKeyParam; + message: MessageDataParam; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + signUp: ( + { + amount, + certificate, + contractAddr, + pubkey + }: { + amount?: string; + certificate?: string; + contractAddr: string; + pubkey: EncPubKeyParam; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + addNewKey: ( + { + contractAddr, + d, + groth16Proof, + nullifier, + pubkey + }: { + contractAddr: string; + d: string[]; + groth16Proof: Groth16ProofParam; + nullifier: string; + pubkey: EncPubKeyParam; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + preAddNewKey: ( + { + contractAddr, + d, + groth16Proof, + nullifier, + pubkey + }: { + contractAddr: string; + d: string[]; + groth16Proof: Groth16ProofParam; + nullifier: string; + pubkey: EncPubKeyParam; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; } export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterface { client: SigningCosmWasmClient; @@ -217,244 +309,426 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac this.addNewKey = this.addNewKey.bind(this); this.preAddNewKey = this.preAddNewKey.bind(this); } - updateConfig = async ({ - admin, - denom - }: { - admin?: Addr; - denom?: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_config: { - admin, - denom - } - }, fee, memo, _funds); + updateConfig = async ( + { + admin, + denom + }: { + admin?: Addr; + denom?: string; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_config: { + admin, + denom + } + }, + fee, + memo, + _funds + ); }; - updateAmaciRegistryContract = async ({ - registryContract - }: { - registryContract: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_amaci_registry_contract: { - registry_contract: registryContract - } - }, fee, memo, _funds); + updateAmaciRegistryContract = async ( + { + registryContract + }: { + registryContract: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_amaci_registry_contract: { + registry_contract: registryContract + } + }, + fee, + memo, + _funds + ); }; - addOperator = async ({ - operator - }: { - operator: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - add_operator: { - operator - } - }, fee, memo, _funds); + addOperator = async ( + { + operator + }: { + operator: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + add_operator: { + operator + } + }, + fee, + memo, + _funds + ); }; - removeOperator = async ({ - operator - }: { - operator: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - remove_operator: { - operator - } - }, fee, memo, _funds); + removeOperator = async ( + { + operator + }: { + operator: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + remove_operator: { + operator + } + }, + fee, + memo, + _funds + ); }; - deposit = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - deposit: {} - }, fee, memo, _funds); + deposit = async ( + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + deposit: {} + }, + fee, + memo, + _funds + ); }; - withdraw = async ({ - amount, - recipient - }: { - amount: Uint128; - recipient?: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - withdraw: { - amount, - recipient - } - }, fee, memo, _funds); + withdraw = async ( + { + amount, + recipient + }: { + amount: Uint128; + recipient?: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + withdraw: { + amount, + recipient + } + }, + fee, + memo, + _funds + ); }; - createAmaciRound = async ({ - certificationSystem, - circuitType, - deactivateEnabled, - operator, - registrationMode, - roundInfo, - voiceCreditMode, - voteOptionMap, - votingTime - }: { - certificationSystem: Uint256; - circuitType: Uint256; - deactivateEnabled: boolean; - operator: Addr; - registrationMode: RegistrationModeConfig; - roundInfo: RoundInfo; - voiceCreditMode: VoiceCreditMode; - voteOptionMap: string[]; - votingTime: VotingTime; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - create_amaci_round: { - certification_system: certificationSystem, - circuit_type: circuitType, - deactivate_enabled: deactivateEnabled, - operator, - registration_mode: registrationMode, - round_info: roundInfo, - voice_credit_mode: voiceCreditMode, - vote_option_map: voteOptionMap, - voting_time: votingTime - } - }, fee, memo, _funds); + createAmaciRound = async ( + { + certificationSystem, + circuitType, + deactivateEnabled, + maxVotesPerOption, + operator, + registrationMode, + roundInfo, + voiceCreditMode, + voteOptionMap, + votingTime + }: { + certificationSystem: Uint256; + circuitType: Uint256; + deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; + operator: Addr; + registrationMode: RegistrationModeConfig; + roundInfo: RoundInfo; + voiceCreditMode: VoiceCreditMode; + voteOptionMap: string[]; + votingTime: VotingTime; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + create_amaci_round: { + certification_system: certificationSystem, + circuit_type: circuitType, + deactivate_enabled: deactivateEnabled, + max_votes_per_option: maxVotesPerOption, + operator, + registration_mode: registrationMode, + round_info: roundInfo, + voice_credit_mode: voiceCreditMode, + vote_option_map: voteOptionMap, + voting_time: votingTime + } + }, + fee, + memo, + _funds + ); }; - updateFeeConfig = async ({ - config - }: { - config: SaasFeeConfig; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_fee_config: { - config - } - }, fee, memo, _funds); + updateFeeConfig = async ( + { + config + }: { + config: SaasFeeConfig; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_fee_config: { + config + } + }, + fee, + memo, + _funds + ); }; - setRoundInfo = async ({ - contractAddr, - roundInfo - }: { - contractAddr: string; - roundInfo: RoundInfo; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_round_info: { - contract_addr: contractAddr, - round_info: roundInfo - } - }, fee, memo, _funds); + setRoundInfo = async ( + { + contractAddr, + roundInfo + }: { + contractAddr: string; + roundInfo: RoundInfo; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_round_info: { + contract_addr: contractAddr, + round_info: roundInfo + } + }, + fee, + memo, + _funds + ); }; - setVoteOptionsMap = async ({ - contractAddr, - voteOptionMap - }: { - contractAddr: string; - voteOptionMap: string[]; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_vote_options_map: { - contract_addr: contractAddr, - vote_option_map: voteOptionMap - } - }, fee, memo, _funds); + setVoteOptionsMap = async ( + { + contractAddr, + voteOptionMap + }: { + contractAddr: string; + voteOptionMap: string[]; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_vote_options_map: { + contract_addr: contractAddr, + vote_option_map: voteOptionMap + } + }, + fee, + memo, + _funds + ); }; - publishMessage = async ({ - contractAddr, - encPubKeys, - messages - }: { - contractAddr: string; - encPubKeys: EncPubKeyParam[]; - messages: MessageDataParam[]; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - publish_message: { - contract_addr: contractAddr, - enc_pub_keys: encPubKeys, - messages - } - }, fee, memo, _funds); + publishMessage = async ( + { + contractAddr, + encPubKeys, + messages + }: { + contractAddr: string; + encPubKeys: EncPubKeyParam[]; + messages: MessageDataParam[]; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + publish_message: { + contract_addr: contractAddr, + enc_pub_keys: encPubKeys, + messages + } + }, + fee, + memo, + _funds + ); }; - publishDeactivateMessage = async ({ - contractAddr, - encPubKey, - message - }: { - contractAddr: string; - encPubKey: EncPubKeyParam; - message: MessageDataParam; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - publish_deactivate_message: { - contract_addr: contractAddr, - enc_pub_key: encPubKey, - message - } - }, fee, memo, _funds); + publishDeactivateMessage = async ( + { + contractAddr, + encPubKey, + message + }: { + contractAddr: string; + encPubKey: EncPubKeyParam; + message: MessageDataParam; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + publish_deactivate_message: { + contract_addr: contractAddr, + enc_pub_key: encPubKey, + message + } + }, + fee, + memo, + _funds + ); }; - signUp = async ({ - amount, - certificate, - contractAddr, - pubkey - }: { - amount?: string; - certificate?: string; - contractAddr: string; - pubkey: EncPubKeyParam; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - sign_up: { - amount, - certificate, - contract_addr: contractAddr, - pubkey - } - }, fee, memo, _funds); + signUp = async ( + { + amount, + certificate, + contractAddr, + pubkey + }: { + amount?: string; + certificate?: string; + contractAddr: string; + pubkey: EncPubKeyParam; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + sign_up: { + amount, + certificate, + contract_addr: contractAddr, + pubkey + } + }, + fee, + memo, + _funds + ); }; - addNewKey = async ({ - contractAddr, - d, - groth16Proof, - nullifier, - pubkey - }: { - contractAddr: string; - d: string[]; - groth16Proof: Groth16ProofParam; - nullifier: string; - pubkey: EncPubKeyParam; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - add_new_key: { - contract_addr: contractAddr, - d, - groth16_proof: groth16Proof, - nullifier, - pubkey - } - }, fee, memo, _funds); + addNewKey = async ( + { + contractAddr, + d, + groth16Proof, + nullifier, + pubkey + }: { + contractAddr: string; + d: string[]; + groth16Proof: Groth16ProofParam; + nullifier: string; + pubkey: EncPubKeyParam; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + add_new_key: { + contract_addr: contractAddr, + d, + groth16_proof: groth16Proof, + nullifier, + pubkey + } + }, + fee, + memo, + _funds + ); }; - preAddNewKey = async ({ - contractAddr, - d, - groth16Proof, - nullifier, - pubkey - }: { - contractAddr: string; - d: string[]; - groth16Proof: Groth16ProofParam; - nullifier: string; - pubkey: EncPubKeyParam; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - pre_add_new_key: { - contract_addr: contractAddr, - d, - groth16_proof: groth16Proof, - nullifier, - pubkey - } - }, fee, memo, _funds); + preAddNewKey = async ( + { + contractAddr, + d, + groth16Proof, + nullifier, + pubkey + }: { + contractAddr: string; + d: string[]; + groth16Proof: Groth16ProofParam; + nullifier: string; + pubkey: EncPubKeyParam; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + pre_add_new_key: { + contract_addr: contractAddr, + d, + groth16_proof: groth16Proof, + nullifier, + pubkey + } + }, + fee, + memo, + _funds + ); }; -} \ No newline at end of file +} diff --git a/contracts/api-saas/ts/ApiSaas.types.ts b/contracts/api-saas/ts/ApiSaas.types.ts index 0c17508a..9558e5f7 100644 --- a/contracts/api-saas/ts/ApiSaas.types.ts +++ b/contracts/api-saas/ts/ApiSaas.types.ts @@ -1,8 +1,8 @@ /** -* This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ + * This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ export type Addr = string; export interface InstantiateMsg { @@ -11,113 +11,134 @@ export interface InstantiateMsg { registry_contract: Addr; treasury_manager: Addr; } -export type ExecuteMsg = { - update_config: { - admin?: Addr | null; - denom?: string | null; - }; -} | { - update_amaci_registry_contract: { - registry_contract: Addr; - }; -} | { - add_operator: { - operator: Addr; - }; -} | { - remove_operator: { - operator: Addr; - }; -} | { - deposit: {}; -} | { - withdraw: { - amount: Uint128; - recipient?: Addr | null; - }; -} | { - create_amaci_round: { - certification_system: Uint256; - circuit_type: Uint256; - deactivate_enabled: boolean; - operator: Addr; - registration_mode: RegistrationModeConfig; - round_info: RoundInfo; - voice_credit_mode: VoiceCreditMode; - vote_option_map: string[]; - voting_time: VotingTime; - }; -} | { - update_fee_config: { - config: SaasFeeConfig; - }; -} | { - set_round_info: { - contract_addr: string; - round_info: RoundInfo; - }; -} | { - set_vote_options_map: { - contract_addr: string; - vote_option_map: string[]; - }; -} | { - publish_message: { - contract_addr: string; - enc_pub_keys: EncPubKeyParam[]; - messages: MessageDataParam[]; - }; -} | { - publish_deactivate_message: { - contract_addr: string; - enc_pub_key: EncPubKeyParam; - message: MessageDataParam; - }; -} | { - sign_up: { - amount?: string | null; - certificate?: string | null; - contract_addr: string; - pubkey: EncPubKeyParam; - }; -} | { - add_new_key: { - contract_addr: string; - d: [string, string, string, string]; - groth16_proof: Groth16ProofParam; - nullifier: string; - pubkey: EncPubKeyParam; - }; -} | { - pre_add_new_key: { - contract_addr: string; - d: [string, string, string, string]; - groth16_proof: Groth16ProofParam; - nullifier: string; - pubkey: EncPubKeyParam; - }; -}; +export type ExecuteMsg = + | { + update_config: { + admin?: Addr | null; + denom?: string | null; + }; + } + | { + update_amaci_registry_contract: { + registry_contract: Addr; + }; + } + | { + add_operator: { + operator: Addr; + }; + } + | { + remove_operator: { + operator: Addr; + }; + } + | { + deposit: {}; + } + | { + withdraw: { + amount: Uint128; + recipient?: Addr | null; + }; + } + | { + create_amaci_round: { + certification_system: Uint256; + circuit_type: Uint256; + deactivate_enabled: boolean; + max_votes_per_option?: Uint256 | null; + operator: Addr; + registration_mode: RegistrationModeConfig; + round_info: RoundInfo; + voice_credit_mode: VoiceCreditMode; + vote_option_map: string[]; + voting_time: VotingTime; + }; + } + | { + update_fee_config: { + config: SaasFeeConfig; + }; + } + | { + set_round_info: { + contract_addr: string; + round_info: RoundInfo; + }; + } + | { + set_vote_options_map: { + contract_addr: string; + vote_option_map: string[]; + }; + } + | { + publish_message: { + contract_addr: string; + enc_pub_keys: EncPubKeyParam[]; + messages: MessageDataParam[]; + }; + } + | { + publish_deactivate_message: { + contract_addr: string; + enc_pub_key: EncPubKeyParam; + message: MessageDataParam; + }; + } + | { + sign_up: { + amount?: string | null; + certificate?: string | null; + contract_addr: string; + pubkey: EncPubKeyParam; + }; + } + | { + add_new_key: { + contract_addr: string; + d: [string, string, string, string]; + groth16_proof: Groth16ProofParam; + nullifier: string; + pubkey: EncPubKeyParam; + }; + } + | { + pre_add_new_key: { + contract_addr: string; + d: [string, string, string, string]; + groth16_proof: Groth16ProofParam; + nullifier: string; + pubkey: EncPubKeyParam; + }; + }; export type Uint128 = string; export type Uint256 = string; -export type RegistrationModeConfig = { - sign_up_with_static_whitelist: { - whitelist: WhitelistBase; - }; -} | { - sign_up_with_oracle: { - oracle_pubkey: string; - }; -} | { - pre_populated: { - pre_deactivate_coordinator: PubKey; - pre_deactivate_root: Uint256; - }; -}; -export type VoiceCreditMode = "dynamic" | { - unified: { - amount: Uint256; - }; -}; +export type RegistrationModeConfig = + | { + sign_up_with_static_whitelist: { + whitelist: WhitelistBase; + }; + } + | { + sign_up_with_oracle: { + oracle_pubkey: string; + }; + } + | { + pre_populated: { + pre_deactivate_coordinator: PubKey; + pre_deactivate_root: Uint256; + }; + }; +export type VoiceCreditMode = + | 'dynamic' + | { + unified: { + amount: Uint256; + }; + }; export type Timestamp = Uint64; export type Uint64 = string; export interface WhitelistBase { @@ -155,19 +176,24 @@ export interface Groth16ProofParam { b: string; c: string; } -export type QueryMsg = { - config: {}; -} | { - operators: {}; -} | { - is_operator: { - address: Addr; - }; -} | { - balance: {}; -} | { - treasury_manager: {}; -}; +export type QueryMsg = + | { + config: {}; + } + | { + operators: {}; + } + | { + is_operator: { + address: Addr; + }; + } + | { + balance: {}; + } + | { + treasury_manager: {}; + }; export interface Config { admin: Addr; denom: string; @@ -177,4 +203,4 @@ export type ArrayOfOperatorInfo = OperatorInfo[]; export interface OperatorInfo { added_at: Timestamp; address: Addr; -} \ No newline at end of file +} diff --git a/contracts/registry/ts/Registry.client.ts b/contracts/registry/ts/Registry.client.ts index ae0319d2..10854c17 100644 --- a/contracts/registry/ts/Registry.client.ts +++ b/contracts/registry/ts/Registry.client.ts @@ -1,55 +1,52 @@ /** -* This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ + * This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { Coin, StdFee } from "@cosmjs/amino"; -import { Addr, InstantiateMsg, ExecuteMsg, Uint256, RegistrationModeConfig, VoiceCreditMode, Timestamp, Uint64, Decimal, Uint128, PubKey, WhitelistBase, WhitelistBaseConfig, RoundInfo, VotingTime, ValidatorSet, CircuitChargeConfig, FeeConfig, DelayConfig, QueryMsg, AdminResponse, String, NullableAddr, Boolean } from "./Registry.types"; +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'; +import { Coin, StdFee } from '@cosmjs/amino'; +import { + Addr, + InstantiateMsg, + ExecuteMsg, + Uint256, + RegistrationModeConfig, + VoiceCreditMode, + Timestamp, + Uint64, + Decimal, + Uint128, + PubKey, + WhitelistBase, + WhitelistBaseConfig, + RoundInfo, + VotingTime, + ValidatorSet, + CircuitChargeConfig, + FeeConfig, + DelayConfig, + QueryMsg, + AdminResponse, + String, + NullableAddr, + Boolean +} from './Registry.types'; export interface RegistryReadOnlyInterface { contractAddress: string; admin: () => Promise; operator: () => Promise; - isMaciOperator: ({ - address - }: { - address: Addr; - }) => Promise; - isValidator: ({ - address - }: { - address: Addr; - }) => Promise; + isMaciOperator: ({ address }: { address: Addr }) => Promise; + isValidator: ({ address }: { address: Addr }) => Promise; getValidators: () => Promise; - getValidatorOperator: ({ - address - }: { - address: Addr; - }) => Promise; - getMaciOperatorPubkey: ({ - address - }: { - address: Addr; - }) => Promise; - getMaciOperatorIdentity: ({ - address - }: { - address: Addr; - }) => Promise; + getValidatorOperator: ({ address }: { address: Addr }) => Promise; + getMaciOperatorPubkey: ({ address }: { address: Addr }) => Promise; + getMaciOperatorIdentity: ({ address }: { address: Addr }) => Promise; getCircuitChargeConfig: () => Promise; getFeeConfig: () => Promise; getDelayConfig: () => Promise; - getPollId: ({ - address - }: { - address: Addr; - }) => Promise; - getPollAddress: ({ - pollId - }: { - pollId: number; - }) => Promise; + getPollId: ({ address }: { address: Addr }) => Promise; + getPollAddress: ({ pollId }: { pollId: number }) => Promise; getNextPollId: () => Promise; getAmaciCodeId: () => Promise; } @@ -85,22 +82,14 @@ export class RegistryQueryClient implements RegistryReadOnlyInterface { operator: {} }); }; - isMaciOperator = async ({ - address - }: { - address: Addr; - }): Promise => { + isMaciOperator = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { is_maci_operator: { address } }); }; - isValidator = async ({ - address - }: { - address: Addr; - }): Promise => { + isValidator = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { is_validator: { address @@ -112,33 +101,21 @@ export class RegistryQueryClient implements RegistryReadOnlyInterface { get_validators: {} }); }; - getValidatorOperator = async ({ - address - }: { - address: Addr; - }): Promise => { + getValidatorOperator = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_validator_operator: { address } }); }; - getMaciOperatorPubkey = async ({ - address - }: { - address: Addr; - }): Promise => { + getMaciOperatorPubkey = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_maci_operator_pubkey: { address } }); }; - getMaciOperatorIdentity = async ({ - address - }: { - address: Addr; - }): Promise => { + getMaciOperatorIdentity = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_maci_operator_identity: { address @@ -160,22 +137,14 @@ export class RegistryQueryClient implements RegistryReadOnlyInterface { get_delay_config: {} }); }; - getPollId = async ({ - address - }: { - address: Addr; - }): Promise => { + getPollId = async ({ address }: { address: Addr }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_poll_id: { address } }); }; - getPollAddress = async ({ - pollId - }: { - pollId: number; - }): Promise => { + getPollAddress = async ({ pollId }: { pollId: number }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_poll_address: { poll_id: pollId @@ -196,77 +165,134 @@ export class RegistryQueryClient implements RegistryReadOnlyInterface { export interface RegistryInterface extends RegistryReadOnlyInterface { contractAddress: string; sender: string; - setMaciOperator: ({ - operator - }: { - operator: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setMaciOperatorPubkey: ({ - pubkey - }: { - pubkey: PubKey; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setMaciOperatorIdentity: ({ - identity - }: { - identity: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - createRound: ({ - certificationSystem, - circuitType, - deactivateEnabled, - operator, - registrationMode, - roundInfo, - voiceCreditMode, - voteOptionMap, - votingTime - }: { - certificationSystem: Uint256; - circuitType: Uint256; - deactivateEnabled: boolean; - operator: Addr; - registrationMode: RegistrationModeConfig; - roundInfo: RoundInfo; - voiceCreditMode: VoiceCreditMode; - voteOptionMap: string[]; - votingTime: VotingTime; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setValidators: ({ - addresses - }: { - addresses: ValidatorSet; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - removeValidator: ({ - address - }: { - address: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateAmaciCodeId: ({ - codeId - }: { - codeId: number; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - changeOperator: ({ - address - }: { - address: Addr; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - changeChargeConfig: ({ - config - }: { - config: CircuitChargeConfig; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateFeeConfig: ({ - config - }: { - config: FeeConfig; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateDelayConfig: ({ - config - }: { - config: DelayConfig; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setMaciOperator: ( + { + operator + }: { + operator: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + setMaciOperatorPubkey: ( + { + pubkey + }: { + pubkey: PubKey; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + setMaciOperatorIdentity: ( + { + identity + }: { + identity: string; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + createRound: ( + { + certificationSystem, + circuitType, + deactivateEnabled, + maxVotesPerOption, + operator, + registrationMode, + roundInfo, + voiceCreditMode, + voteOptionMap, + votingTime + }: { + certificationSystem: Uint256; + circuitType: Uint256; + deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; + operator: Addr; + registrationMode: RegistrationModeConfig; + roundInfo: RoundInfo; + voiceCreditMode: VoiceCreditMode; + voteOptionMap: string[]; + votingTime: VotingTime; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + setValidators: ( + { + addresses + }: { + addresses: ValidatorSet; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + removeValidator: ( + { + address + }: { + address: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + updateAmaciCodeId: ( + { + codeId + }: { + codeId: number; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + changeOperator: ( + { + address + }: { + address: Addr; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + changeChargeConfig: ( + { + config + }: { + config: CircuitChargeConfig; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + updateFeeConfig: ( + { + config + }: { + config: FeeConfig; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; + updateDelayConfig: ( + { + config + }: { + config: DelayConfig; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; } export class RegistryClient extends RegistryQueryClient implements RegistryInterface { client: SigningCosmWasmClient; @@ -289,149 +315,284 @@ export class RegistryClient extends RegistryQueryClient implements RegistryInter this.updateFeeConfig = this.updateFeeConfig.bind(this); this.updateDelayConfig = this.updateDelayConfig.bind(this); } - setMaciOperator = async ({ - operator - }: { - operator: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_maci_operator: { - operator - } - }, fee, memo, _funds); + setMaciOperator = async ( + { + operator + }: { + operator: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_maci_operator: { + operator + } + }, + fee, + memo, + _funds + ); }; - setMaciOperatorPubkey = async ({ - pubkey - }: { - pubkey: PubKey; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_maci_operator_pubkey: { - pubkey - } - }, fee, memo, _funds); + setMaciOperatorPubkey = async ( + { + pubkey + }: { + pubkey: PubKey; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_maci_operator_pubkey: { + pubkey + } + }, + fee, + memo, + _funds + ); }; - setMaciOperatorIdentity = async ({ - identity - }: { - identity: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_maci_operator_identity: { - identity - } - }, fee, memo, _funds); + setMaciOperatorIdentity = async ( + { + identity + }: { + identity: string; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_maci_operator_identity: { + identity + } + }, + fee, + memo, + _funds + ); }; - createRound = async ({ - certificationSystem, - circuitType, - deactivateEnabled, - operator, - registrationMode, - roundInfo, - voiceCreditMode, - voteOptionMap, - votingTime - }: { - certificationSystem: Uint256; - circuitType: Uint256; - deactivateEnabled: boolean; - operator: Addr; - registrationMode: RegistrationModeConfig; - roundInfo: RoundInfo; - voiceCreditMode: VoiceCreditMode; - voteOptionMap: string[]; - votingTime: VotingTime; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - create_round: { - certification_system: certificationSystem, - circuit_type: circuitType, - deactivate_enabled: deactivateEnabled, - operator, - registration_mode: registrationMode, - round_info: roundInfo, - voice_credit_mode: voiceCreditMode, - vote_option_map: voteOptionMap, - voting_time: votingTime - } - }, fee, memo, _funds); + createRound = async ( + { + certificationSystem, + circuitType, + deactivateEnabled, + maxVotesPerOption, + operator, + registrationMode, + roundInfo, + voiceCreditMode, + voteOptionMap, + votingTime + }: { + certificationSystem: Uint256; + circuitType: Uint256; + deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; + operator: Addr; + registrationMode: RegistrationModeConfig; + roundInfo: RoundInfo; + voiceCreditMode: VoiceCreditMode; + voteOptionMap: string[]; + votingTime: VotingTime; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + create_round: { + certification_system: certificationSystem, + circuit_type: circuitType, + deactivate_enabled: deactivateEnabled, + max_votes_per_option: maxVotesPerOption, + operator, + registration_mode: registrationMode, + round_info: roundInfo, + voice_credit_mode: voiceCreditMode, + vote_option_map: voteOptionMap, + voting_time: votingTime + } + }, + fee, + memo, + _funds + ); }; - setValidators = async ({ - addresses - }: { - addresses: ValidatorSet; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_validators: { - addresses - } - }, fee, memo, _funds); + setValidators = async ( + { + addresses + }: { + addresses: ValidatorSet; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_validators: { + addresses + } + }, + fee, + memo, + _funds + ); }; - removeValidator = async ({ - address - }: { - address: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - remove_validator: { - address - } - }, fee, memo, _funds); + removeValidator = async ( + { + address + }: { + address: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + remove_validator: { + address + } + }, + fee, + memo, + _funds + ); }; - updateAmaciCodeId = async ({ - codeId - }: { - codeId: number; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_amaci_code_id: { - code_id: codeId - } - }, fee, memo, _funds); + updateAmaciCodeId = async ( + { + codeId + }: { + codeId: number; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_amaci_code_id: { + code_id: codeId + } + }, + fee, + memo, + _funds + ); }; - changeOperator = async ({ - address - }: { - address: Addr; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - change_operator: { - address - } - }, fee, memo, _funds); + changeOperator = async ( + { + address + }: { + address: Addr; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + change_operator: { + address + } + }, + fee, + memo, + _funds + ); }; - changeChargeConfig = async ({ - config - }: { - config: CircuitChargeConfig; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - change_charge_config: { - config - } - }, fee, memo, _funds); + changeChargeConfig = async ( + { + config + }: { + config: CircuitChargeConfig; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + change_charge_config: { + config + } + }, + fee, + memo, + _funds + ); }; - updateFeeConfig = async ({ - config - }: { - config: FeeConfig; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_fee_config: { - config - } - }, fee, memo, _funds); + updateFeeConfig = async ( + { + config + }: { + config: FeeConfig; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_fee_config: { + config + } + }, + fee, + memo, + _funds + ); }; - updateDelayConfig = async ({ - config - }: { - config: DelayConfig; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_delay_config: { - config - } - }, fee, memo, _funds); + updateDelayConfig = async ( + { + config + }: { + config: DelayConfig; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + update_delay_config: { + config + } + }, + fee, + memo, + _funds + ); }; -} \ No newline at end of file +} diff --git a/contracts/registry/ts/Registry.types.ts b/contracts/registry/ts/Registry.types.ts index b0a20ff3..39224de3 100644 --- a/contracts/registry/ts/Registry.types.ts +++ b/contracts/registry/ts/Registry.types.ts @@ -1,8 +1,8 @@ /** -* This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ + * This file was automatically generated by @cosmwasm/ts-codegen@1.11.1. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ export type Addr = string; export interface InstantiateMsg { @@ -10,79 +10,96 @@ export interface InstantiateMsg { amaci_code_id: number; operator: Addr; } -export type ExecuteMsg = { - set_maci_operator: { - operator: Addr; - }; -} | { - set_maci_operator_pubkey: { - pubkey: PubKey; - }; -} | { - set_maci_operator_identity: { - identity: string; - }; -} | { - create_round: { - certification_system: Uint256; - circuit_type: Uint256; - deactivate_enabled: boolean; - operator: Addr; - registration_mode: RegistrationModeConfig; - round_info: RoundInfo; - voice_credit_mode: VoiceCreditMode; - vote_option_map: string[]; - voting_time: VotingTime; - }; -} | { - set_validators: { - addresses: ValidatorSet; - }; -} | { - remove_validator: { - address: Addr; - }; -} | { - update_amaci_code_id: { - code_id: number; - }; -} | { - change_operator: { - address: Addr; - }; -} | { - change_charge_config: { - config: CircuitChargeConfig; - }; -} | { - update_fee_config: { - config: FeeConfig; - }; -} | { - update_delay_config: { - config: DelayConfig; - }; -}; +export type ExecuteMsg = + | { + set_maci_operator: { + operator: Addr; + }; + } + | { + set_maci_operator_pubkey: { + pubkey: PubKey; + }; + } + | { + set_maci_operator_identity: { + identity: string; + }; + } + | { + create_round: { + certification_system: Uint256; + circuit_type: Uint256; + deactivate_enabled: boolean; + max_votes_per_option?: Uint256 | null; + operator: Addr; + registration_mode: RegistrationModeConfig; + round_info: RoundInfo; + voice_credit_mode: VoiceCreditMode; + vote_option_map: string[]; + voting_time: VotingTime; + }; + } + | { + set_validators: { + addresses: ValidatorSet; + }; + } + | { + remove_validator: { + address: Addr; + }; + } + | { + update_amaci_code_id: { + code_id: number; + }; + } + | { + change_operator: { + address: Addr; + }; + } + | { + change_charge_config: { + config: CircuitChargeConfig; + }; + } + | { + update_fee_config: { + config: FeeConfig; + }; + } + | { + update_delay_config: { + config: DelayConfig; + }; + }; export type Uint256 = string; -export type RegistrationModeConfig = { - sign_up_with_static_whitelist: { - whitelist: WhitelistBase; - }; -} | { - sign_up_with_oracle: { - oracle_pubkey: string; - }; -} | { - pre_populated: { - pre_deactivate_coordinator: PubKey; - pre_deactivate_root: Uint256; - }; -}; -export type VoiceCreditMode = "dynamic" | { - unified: { - amount: Uint256; - }; -}; +export type RegistrationModeConfig = + | { + sign_up_with_static_whitelist: { + whitelist: WhitelistBase; + }; + } + | { + sign_up_with_oracle: { + oracle_pubkey: string; + }; + } + | { + pre_populated: { + pre_deactivate_coordinator: PubKey; + pre_deactivate_root: Uint256; + }; + }; +export type VoiceCreditMode = + | 'dynamic' + | { + unified: { + amount: Uint256; + }; + }; export type Timestamp = Uint64; export type Uint64 = number; export type Decimal = string; @@ -125,54 +142,69 @@ export interface DelayConfig { message_delay: number; signup_delay: number; } -export type QueryMsg = { - admin: {}; -} | { - operator: {}; -} | { - is_maci_operator: { - address: Addr; - }; -} | { - is_validator: { - address: Addr; - }; -} | { - get_validators: {}; -} | { - get_validator_operator: { - address: Addr; - }; -} | { - get_maci_operator_pubkey: { - address: Addr; - }; -} | { - get_maci_operator_identity: { - address: Addr; - }; -} | { - get_circuit_charge_config: {}; -} | { - get_fee_config: {}; -} | { - get_delay_config: {}; -} | { - get_poll_id: { - address: Addr; - }; -} | { - get_poll_address: { - poll_id: number; - }; -} | { - get_next_poll_id: {}; -} | { - get_amaci_code_id: {}; -}; +export type QueryMsg = + | { + admin: {}; + } + | { + operator: {}; + } + | { + is_maci_operator: { + address: Addr; + }; + } + | { + is_validator: { + address: Addr; + }; + } + | { + get_validators: {}; + } + | { + get_validator_operator: { + address: Addr; + }; + } + | { + get_maci_operator_pubkey: { + address: Addr; + }; + } + | { + get_maci_operator_identity: { + address: Addr; + }; + } + | { + get_circuit_charge_config: {}; + } + | { + get_fee_config: {}; + } + | { + get_delay_config: {}; + } + | { + get_poll_id: { + address: Addr; + }; + } + | { + get_poll_address: { + poll_id: number; + }; + } + | { + get_next_poll_id: {}; + } + | { + get_amaci_code_id: {}; + }; export interface AdminResponse { admin: Addr; } export type String = string; export type NullableAddr = Addr | null; -export type Boolean = boolean; \ No newline at end of file +export type Boolean = boolean; diff --git a/packages/sdk/src/libs/contract/ts/AMaci.client.ts b/packages/sdk/src/libs/contract/ts/AMaci.client.ts index beafa802..9c8f45b8 100644 --- a/packages/sdk/src/libs/contract/ts/AMaci.client.ts +++ b/packages/sdk/src/libs/contract/ts/AMaci.client.ts @@ -38,6 +38,8 @@ import { RegistrationMode, RegistrationConfigInfo, TallyDelayInfo, + VkeysResponse, + Groth16VkeyStr, NullableString, NullableUint256, RegistrationStatus, @@ -66,6 +68,7 @@ export interface AMaciReadOnlyInterface { signuped: ({ pubkey }: { pubkey: PubKey }) => Promise; voteOptionMap: () => Promise; maxVoteOptions: () => Promise; + maxVotesPerOption: () => Promise; queryCircuitType: () => Promise; queryCertSystem: () => Promise; queryPreDeactivateRoot: () => Promise; @@ -93,6 +96,7 @@ export interface AMaciReadOnlyInterface { }) => Promise; getFeeConfig: () => Promise; getDelayConfig: () => Promise; + getVkeys: () => Promise; } export class AMaciQueryClient implements AMaciReadOnlyInterface { client: CosmWasmClient; @@ -121,6 +125,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { this.signuped = this.signuped.bind(this); this.voteOptionMap = this.voteOptionMap.bind(this); this.maxVoteOptions = this.maxVoteOptions.bind(this); + this.maxVotesPerOption = this.maxVotesPerOption.bind(this); this.queryCircuitType = this.queryCircuitType.bind(this); this.queryCertSystem = this.queryCertSystem.bind(this); this.queryPreDeactivateRoot = this.queryPreDeactivateRoot.bind(this); @@ -138,6 +143,7 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { this.queryRegistrationStatus = this.queryRegistrationStatus.bind(this); this.getFeeConfig = this.getFeeConfig.bind(this); this.getDelayConfig = this.getDelayConfig.bind(this); + this.getVkeys = this.getVkeys.bind(this); } admin = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { @@ -252,6 +258,11 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { max_vote_options: {} }); }; + maxVotesPerOption = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + max_votes_per_option: {} + }); + }; queryCircuitType = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { query_circuit_type: {} @@ -354,6 +365,11 @@ export class AMaciQueryClient implements AMaciReadOnlyInterface { get_delay_config: {} }); }; + getVkeys = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_vkeys: {} + }); + }; } export interface AMaciInterface extends AMaciReadOnlyInterface { contractAddress: string; diff --git a/packages/sdk/src/libs/contract/ts/AMaci.types.ts b/packages/sdk/src/libs/contract/ts/AMaci.types.ts index 73f1f8df..50a78038 100644 --- a/packages/sdk/src/libs/contract/ts/AMaci.types.ts +++ b/packages/sdk/src/libs/contract/ts/AMaci.types.ts @@ -43,6 +43,7 @@ export interface InstantiateMsg { deactivate_enabled: boolean; deactivate_fee: Uint128; fee_recipient: Addr; + max_votes_per_option?: Uint256 | null; message_delay: number; message_fee: Uint128; operator: Addr; @@ -253,6 +254,9 @@ export type QueryMsg = | { max_vote_options: {}; } + | { + max_votes_per_option: {}; + } | { query_circuit_type: {}; } @@ -310,6 +314,9 @@ export type QueryMsg = } | { get_delay_config: {}; + } + | { + get_vkeys: {}; }; export type ArrayOfUint256 = Uint256[]; export type Boolean = boolean; @@ -364,6 +371,20 @@ export interface TallyDelayInfo { num_sign_ups: Uint256; total_work: number; } +export interface VkeysResponse { + add_key_vkey: Groth16VkeyStr; + deactivate_vkey: Groth16VkeyStr; + process_vkey: Groth16VkeyStr; + tally_vkey: Groth16VkeyStr; +} +export interface Groth16VkeyStr { + alpha_1: number[]; + beta_2: number[]; + delta_2: number[]; + gamma_2: number[]; + ic0: number[]; + ic1: number[]; +} export type NullableString = string | null; export type NullableUint256 = Uint256 | null; export interface RegistrationStatus { diff --git a/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts b/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts index 9f184ac5..370ec0ce 100644 --- a/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts +++ b/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts @@ -146,6 +146,7 @@ export interface ApiSaasInterface extends ApiSaasReadOnlyInterface { certificationSystem, circuitType, deactivateEnabled, + maxVotesPerOption, operator, registrationMode, roundInfo, @@ -156,6 +157,7 @@ export interface ApiSaasInterface extends ApiSaasReadOnlyInterface { certificationSystem: Uint256; circuitType: Uint256; deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; operator: Addr; registrationMode: RegistrationModeConfig; roundInfo: RoundInfo; @@ -449,6 +451,7 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac certificationSystem, circuitType, deactivateEnabled, + maxVotesPerOption, operator, registrationMode, roundInfo, @@ -459,6 +462,7 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac certificationSystem: Uint256; circuitType: Uint256; deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; operator: Addr; registrationMode: RegistrationModeConfig; roundInfo: RoundInfo; @@ -478,6 +482,7 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac certification_system: certificationSystem, circuit_type: circuitType, deactivate_enabled: deactivateEnabled, + max_votes_per_option: maxVotesPerOption, operator, registration_mode: registrationMode, round_info: roundInfo, diff --git a/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts b/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts index 0ded4285..9558e5f7 100644 --- a/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts +++ b/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts @@ -47,6 +47,7 @@ export type ExecuteMsg = certification_system: Uint256; circuit_type: Uint256; deactivate_enabled: boolean; + max_votes_per_option?: Uint256 | null; operator: Addr; registration_mode: RegistrationModeConfig; round_info: RoundInfo; diff --git a/packages/sdk/src/libs/contract/ts/Registry.client.ts b/packages/sdk/src/libs/contract/ts/Registry.client.ts index ef73fa7b..10854c17 100644 --- a/packages/sdk/src/libs/contract/ts/Registry.client.ts +++ b/packages/sdk/src/libs/contract/ts/Registry.client.ts @@ -200,6 +200,7 @@ export interface RegistryInterface extends RegistryReadOnlyInterface { certificationSystem, circuitType, deactivateEnabled, + maxVotesPerOption, operator, registrationMode, roundInfo, @@ -210,6 +211,7 @@ export interface RegistryInterface extends RegistryReadOnlyInterface { certificationSystem: Uint256; circuitType: Uint256; deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; operator: Addr; registrationMode: RegistrationModeConfig; roundInfo: RoundInfo; @@ -387,6 +389,7 @@ export class RegistryClient extends RegistryQueryClient implements RegistryInter certificationSystem, circuitType, deactivateEnabled, + maxVotesPerOption, operator, registrationMode, roundInfo, @@ -397,6 +400,7 @@ export class RegistryClient extends RegistryQueryClient implements RegistryInter certificationSystem: Uint256; circuitType: Uint256; deactivateEnabled: boolean; + maxVotesPerOption?: Uint256; operator: Addr; registrationMode: RegistrationModeConfig; roundInfo: RoundInfo; @@ -416,6 +420,7 @@ export class RegistryClient extends RegistryQueryClient implements RegistryInter certification_system: certificationSystem, circuit_type: circuitType, deactivate_enabled: deactivateEnabled, + max_votes_per_option: maxVotesPerOption, operator, registration_mode: registrationMode, round_info: roundInfo, diff --git a/packages/sdk/src/libs/contract/ts/Registry.types.ts b/packages/sdk/src/libs/contract/ts/Registry.types.ts index 4598069e..33510143 100644 --- a/packages/sdk/src/libs/contract/ts/Registry.types.ts +++ b/packages/sdk/src/libs/contract/ts/Registry.types.ts @@ -31,6 +31,7 @@ export type ExecuteMsg = certification_system: Uint256; circuit_type: Uint256; deactivate_enabled: boolean; + max_votes_per_option?: Uint256 | null; operator: Addr; registration_mode: RegistrationModeConfig; round_info: RoundInfo; From 579106f4693a7cc5691177bbfb45f06764bb803d Mon Sep 17 00:00:00 2001 From: 99Kies <1290017556@qq.com> Date: Mon, 20 Jul 2026 12:36:48 +0800 Subject: [PATCH 3/6] feat: allow updating max_votes_per_option before voting starts - amaci: add ExecuteMsg::SetMaxVotesPerOption, restricted the same way as SetRoundInfo (admin-only, only before voting starts); extract the 32-bit bound check into a shared validate_max_votes_per_option used by both instantiate and the new update path - api-saas: add SetMaxVotesPerOption proxy execute msg (operator-gated, forwards to the target amaci round which enforces its own admin+timing checks) - regenerate amaci/api-saas JSON schema and cosmwasm-ts-codegen TS client/types (both contracts/*/ts and packages/sdk mirrors) - sdk: add setApiSaasMaciRoundMaxVotesPerOption and getMaxVotesPerOption to packages/sdk/src/libs/contract/contract.ts - amaci multitest: add set_max_votes_per_option helper and 5 tests covering success-before-voting, PeriodError after/at voting start, Unauthorized for non-admin, and MaxVotesPerOptionExceeded on update --- contracts/amaci/schema/cw-amaci.json | 21 +++ contracts/amaci/schema/raw/execute.json | 21 +++ contracts/amaci/src/contract.rs | 50 ++++++- contracts/amaci/src/msg.rs | 5 + contracts/amaci/src/multitest/mod.rs | 17 +++ contracts/amaci/src/multitest/tests.rs | 128 ++++++++++++++++++ contracts/amaci/ts/AMaci.client.ts | 34 +++++ contracts/amaci/ts/AMaci.types.ts | 5 + contracts/api-saas/schema/cw-api-saas.json | 25 ++++ contracts/api-saas/schema/raw/execute.json | 25 ++++ contracts/api-saas/src/contract.rs | 43 ++++++ contracts/api-saas/src/msg.rs | 6 + contracts/api-saas/ts/ApiSaas.client.ts | 39 ++++++ contracts/api-saas/ts/ApiSaas.types.ts | 6 + packages/sdk/src/libs/contract/contract.ts | 59 ++++++++ .../sdk/src/libs/contract/ts/AMaci.client.ts | 34 +++++ .../sdk/src/libs/contract/ts/AMaci.types.ts | 5 + .../src/libs/contract/ts/ApiSaas.client.ts | 39 ++++++ .../sdk/src/libs/contract/ts/ApiSaas.types.ts | 6 + 19 files changed, 563 insertions(+), 5 deletions(-) diff --git a/contracts/amaci/schema/cw-amaci.json b/contracts/amaci/schema/cw-amaci.json index d4b885ae..847a5481 100644 --- a/contracts/amaci/schema/cw-amaci.json +++ b/contracts/amaci/schema/cw-amaci.json @@ -431,6 +431,27 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "set_max_votes_per_option" + ], + "properties": { + "set_max_votes_per_option": { + "type": "object", + "required": [ + "max_votes_per_option" + ], + "properties": { + "max_votes_per_option": { + "$ref": "#/definitions/Uint256" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/amaci/schema/raw/execute.json b/contracts/amaci/schema/raw/execute.json index d7a17ee2..d647f3b5 100644 --- a/contracts/amaci/schema/raw/execute.json +++ b/contracts/amaci/schema/raw/execute.json @@ -68,6 +68,27 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "set_max_votes_per_option" + ], + "properties": { + "set_max_votes_per_option": { + "type": "object", + "required": [ + "max_votes_per_option" + ], + "properties": { + "max_votes_per_option": { + "$ref": "#/definitions/Uint256" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/amaci/src/contract.rs b/contracts/amaci/src/contract.rs index 57b50df5..8c3dd943 100644 --- a/contracts/amaci/src/contract.rs +++ b/contracts/amaci/src/contract.rs @@ -554,11 +554,7 @@ pub fn instantiate( // Per-option vote weight cap (0 = no limit). Must fit in the 32-bit // packedVals slot consumed by the process circuit. let max_votes_per_option = msg.max_votes_per_option.unwrap_or(Uint256::zero()); - if max_votes_per_option >= Uint256::from_u128(1u128 << 32) { - return Err(ContractError::MaxVotesPerOptionExceeded { - current: max_votes_per_option, - }); - } + validate_max_votes_per_option(max_votes_per_option)?; MAX_VOTES_PER_OPTION.save(deps.storage, &max_votes_per_option)?; // ============================================ @@ -801,6 +797,9 @@ pub fn execute( ExecuteMsg::SetVoteOptionsMap { vote_option_map } => { execute_set_vote_options_map(deps, env, info, vote_option_map) } + ExecuteMsg::SetMaxVotesPerOption { + max_votes_per_option, + } => execute_set_max_votes_per_option(deps, env, info, max_votes_per_option), // ExecuteMsg::StartVotingPeriod {} => execute_start_voting_period(deps, env, info), ExecuteMsg::SignUp { pubkey, @@ -897,6 +896,47 @@ pub fn execute_set_round_info( } } +// Shared 32-bit bound check for max_votes_per_option, used both at +// instantiation and by the post-creation SetMaxVotesPerOption update below. +// The value must fit in the 32-bit packedVals slot consumed by the process +// circuit (bits 96-127); anything >= 2^32 would corrupt the packed layout. +fn validate_max_votes_per_option(max_votes_per_option: Uint256) -> Result<(), ContractError> { + if max_votes_per_option >= Uint256::from_u128(1u128 << 32) { + return Err(ContractError::MaxVotesPerOptionExceeded { + current: max_votes_per_option, + }); + } + Ok(()) +} + +// Update the round's per-option vote weight cap after creation. Mirrors +// execute_set_round_info's restrictions exactly: admin-only, and only +// allowed before voting starts (max_votes_per_option is baked into the +// process circuit's packedVals/inputHash, so changing it mid-round would +// make already-signed messages ambiguous about which cap applies to them). +pub fn execute_set_max_votes_per_option( + deps: DepsMut, + env: Env, + info: MessageInfo, + max_votes_per_option: Uint256, +) -> Result { + let voting_time = VOTINGTIME.load(deps.storage)?; + if env.block.time >= voting_time.start_time { + return Err(ContractError::PeriodError {}); + } + + if !is_admin(deps.as_ref(), info.sender.as_ref())? { + return Err(ContractError::Unauthorized {}); + } + + validate_max_votes_per_option(max_votes_per_option)?; + MAX_VOTES_PER_OPTION.save(deps.storage, &max_votes_per_option)?; + + Ok(Response::new() + .add_attribute("action", "set_max_votes_per_option") + .add_attribute("max_votes_per_option", max_votes_per_option.to_string())) +} + // Helper function to validate registration config update fn validate_registration_config_update( deps: &DepsMut, diff --git a/contracts/amaci/src/msg.rs b/contracts/amaci/src/msg.rs index 31c941d0..c0a257ee 100644 --- a/contracts/amaci/src/msg.rs +++ b/contracts/amaci/src/msg.rs @@ -141,6 +141,11 @@ pub enum ExecuteMsg { SetVoteOptionsMap { vote_option_map: Vec, }, + // Admin-only, only allowed before voting starts (same restriction as + // SetRoundInfo). See execute_set_max_votes_per_option for details. + SetMaxVotesPerOption { + max_votes_per_option: Uint256, + }, SignUp { pubkey: PubKey, // user's pubkey // Oracle mode parameter (optional for SignUpWithStaticWhitelist mode, required for SignUpWithOracle mode) diff --git a/contracts/amaci/src/multitest/mod.rs b/contracts/amaci/src/multitest/mod.rs index beb1c0bf..c3798b17 100644 --- a/contracts/amaci/src/multitest/mod.rs +++ b/contracts/amaci/src/multitest/mod.rs @@ -643,6 +643,23 @@ impl MaciContract { ) } + #[track_caller] + pub fn set_max_votes_per_option( + &self, + app: &mut App, + sender: Addr, + max_votes_per_option: Uint256, + ) -> AnyResult { + app.execute_contract( + sender, + self.addr(), + &ExecuteMsg::SetMaxVotesPerOption { + max_votes_per_option, + }, + &[], + ) + } + #[track_caller] pub fn set_vote_option_map(&self, app: &mut App, sender: Addr) -> AnyResult { app.execute_contract( diff --git a/contracts/amaci/src/multitest/tests.rs b/contracts/amaci/src/multitest/tests.rs index 9e29bcbf..83a4a388 100644 --- a/contracts/amaci/src/multitest/tests.rs +++ b/contracts/amaci/src/multitest/tests.rs @@ -4555,6 +4555,134 @@ mod test { ); } + // ── set_max_votes_per_option permission tests ───────────────────────────── + // Mirrors the set_round_info permission tests above: admin-only, and only + // allowed strictly before voting starts (same PeriodError boundary). + + #[test] + fn test_set_max_votes_per_option_success_before_voting() { + let mut app = create_app(); + + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000 - 60_000_000_000); + }); + + let maci_contract = MaciContract::instantiate_default(&mut app, false).unwrap(); + + let result = + maci_contract.set_max_votes_per_option(&mut app, owner(), Uint256::from_u128(42u128)); + assert!( + result.is_ok(), + "Admin should be able to set max_votes_per_option before voting starts" + ); + + let cap: Uint256 = app + .wrap() + .query_wasm_smart(maci_contract.addr(), &QueryMsg::MaxVotesPerOption {}) + .unwrap(); + assert_eq!(cap, Uint256::from_u128(42u128)); + } + + #[test] + fn test_set_max_votes_per_option_fails_after_voting_starts() { + let mut app = create_app(); + + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000 - 60_000_000_000); + }); + + let maci_contract = MaciContract::instantiate_default(&mut app, false).unwrap(); + + // Advance to after voting start + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000 + 60_000_000_000); + }); + + let err = maci_contract + .set_max_votes_per_option(&mut app, owner(), Uint256::from_u128(42u128)) + .unwrap_err(); + + let contract_err: ContractError = err.downcast().unwrap(); + assert_eq!( + contract_err, + ContractError::PeriodError {}, + "Should not be able to set max_votes_per_option after voting starts" + ); + } + + #[test] + fn test_set_max_votes_per_option_fails_exactly_at_voting_start() { + let mut app = create_app(); + + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000 - 60_000_000_000); + }); + + let maci_contract = MaciContract::instantiate_default(&mut app, false).unwrap(); + + // Set block time exactly to voting start_time + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000); + }); + + let err = maci_contract + .set_max_votes_per_option(&mut app, owner(), Uint256::from_u128(42u128)) + .unwrap_err(); + + let contract_err: ContractError = err.downcast().unwrap(); + assert_eq!( + contract_err, + ContractError::PeriodError {}, + "Should not be able to set max_votes_per_option at exact voting start time" + ); + } + + #[test] + fn test_set_max_votes_per_option_unauthorized() { + let mut app = create_app(); + + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000 - 60_000_000_000); + }); + + let maci_contract = MaciContract::instantiate_default(&mut app, false).unwrap(); + + let err = maci_contract + .set_max_votes_per_option(&mut app, user1(), Uint256::from_u128(42u128)) + .unwrap_err(); + + let contract_err: ContractError = err.downcast().unwrap(); + assert_eq!( + contract_err, + ContractError::Unauthorized {}, + "Non-admin should not be able to set max_votes_per_option" + ); + } + + #[test] + fn test_set_max_votes_per_option_rejects_over_32_bits() { + let mut app = create_app(); + + app.update_block(|block| { + block.time = Timestamp::from_nanos(1571797424879000000 - 60_000_000_000); + }); + + let maci_contract = MaciContract::instantiate_default(&mut app, false).unwrap(); + + let err = maci_contract + .set_max_votes_per_option(&mut app, owner(), Uint256::from_u128(1u128 << 32)) + .unwrap_err(); + + let contract_err: ContractError = err.downcast().unwrap(); + assert_eq!( + contract_err, + ContractError::MaxVotesPerOptionExceeded { + current: Uint256::from_u128(1u128 << 32), + }, + "Values >= 2^32 must still be rejected on update, not just at instantiation" + ); + } + // ============================================================ // Edge-case behavioral tests // ============================================================ diff --git a/contracts/amaci/ts/AMaci.client.ts b/contracts/amaci/ts/AMaci.client.ts index 9c8f45b8..f44c542b 100644 --- a/contracts/amaci/ts/AMaci.client.ts +++ b/contracts/amaci/ts/AMaci.client.ts @@ -404,6 +404,16 @@ export interface AMaciInterface extends AMaciReadOnlyInterface { memo?: string, _funds?: Coin[] ) => Promise; + setMaxVotesPerOption: ( + { + maxVotesPerOption + }: { + maxVotesPerOption: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; signUp: ( { amount, @@ -550,6 +560,7 @@ export class AMaciClient extends AMaciQueryClient implements AMaciInterface { this.setRoundInfo = this.setRoundInfo.bind(this); this.updateRegistrationConfig = this.updateRegistrationConfig.bind(this); this.setVoteOptionsMap = this.setVoteOptionsMap.bind(this); + this.setMaxVotesPerOption = this.setMaxVotesPerOption.bind(this); this.signUp = this.signUp.bind(this); this.startProcessPeriod = this.startProcessPeriod.bind(this); this.publishDeactivateMessage = this.publishDeactivateMessage.bind(this); @@ -632,6 +643,29 @@ export class AMaciClient extends AMaciQueryClient implements AMaciInterface { _funds ); }; + setMaxVotesPerOption = async ( + { + maxVotesPerOption + }: { + maxVotesPerOption: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_max_votes_per_option: { + max_votes_per_option: maxVotesPerOption + } + }, + fee, + memo, + _funds + ); + }; signUp = async ( { amount, diff --git a/contracts/amaci/ts/AMaci.types.ts b/contracts/amaci/ts/AMaci.types.ts index 50a78038..2686c05d 100644 --- a/contracts/amaci/ts/AMaci.types.ts +++ b/contracts/amaci/ts/AMaci.types.ts @@ -99,6 +99,11 @@ export type ExecuteMsg = vote_option_map: string[]; }; } + | { + set_max_votes_per_option: { + max_votes_per_option: Uint256; + }; + } | { sign_up: { amount?: Uint256 | null; diff --git a/contracts/api-saas/schema/cw-api-saas.json b/contracts/api-saas/schema/cw-api-saas.json index 84f889dc..7a503465 100644 --- a/contracts/api-saas/schema/cw-api-saas.json +++ b/contracts/api-saas/schema/cw-api-saas.json @@ -317,6 +317,31 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "set_max_votes_per_option" + ], + "properties": { + "set_max_votes_per_option": { + "type": "object", + "required": [ + "contract_addr", + "max_votes_per_option" + ], + "properties": { + "contract_addr": { + "type": "string" + }, + "max_votes_per_option": { + "$ref": "#/definitions/Uint256" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/api-saas/schema/raw/execute.json b/contracts/api-saas/schema/raw/execute.json index abc91588..297f1169 100644 --- a/contracts/api-saas/schema/raw/execute.json +++ b/contracts/api-saas/schema/raw/execute.json @@ -281,6 +281,31 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "set_max_votes_per_option" + ], + "properties": { + "set_max_votes_per_option": { + "type": "object", + "required": [ + "contract_addr", + "max_votes_per_option" + ], + "properties": { + "contract_addr": { + "type": "string" + }, + "max_votes_per_option": { + "$ref": "#/definitions/Uint256" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/api-saas/src/contract.rs b/contracts/api-saas/src/contract.rs index 91719606..2497f753 100644 --- a/contracts/api-saas/src/contract.rs +++ b/contracts/api-saas/src/contract.rs @@ -106,6 +106,10 @@ pub fn execute( contract_addr, vote_option_map, } => execute_set_vote_options_map(deps, env, info, contract_addr, vote_option_map), + ExecuteMsg::SetMaxVotesPerOption { + contract_addr, + max_votes_per_option, + } => execute_set_max_votes_per_option(deps, env, info, contract_addr, max_votes_per_option), ExecuteMsg::PublishMessage { contract_addr, enc_pub_keys, @@ -468,6 +472,45 @@ pub fn execute_set_round_info( .add_attribute("round_title", round_info.title)) } +pub fn execute_set_max_votes_per_option( + deps: DepsMut, + _env: Env, + info: MessageInfo, + contract_addr: String, + max_votes_per_option: Uint256, +) -> Result { + // Only operators can manage Oracle MACI contracts + if !OPERATORS.has(deps.storage, &info.sender) { + return Err(ContractError::Unauthorized {}); + } + + // Validate the contract address format + let target_addr = deps.api.addr_validate(&contract_addr)?; + + // Create Oracle MACI SetMaxVotesPerOption message. The target amaci + // round enforces its own admin-only + pre-voting checks; this proxy + // only gates who is allowed to trigger the call from the SAAS side. + let oracle_maci_msg = serde_json::json!({ + "set_max_votes_per_option": { + "max_votes_per_option": max_votes_per_option + } + }); + + // Execute the contract call + let execute_msg = WasmMsg::Execute { + contract_addr: target_addr.to_string(), + msg: to_json_binary(&oracle_maci_msg)?, + funds: vec![], + }; + + Ok(Response::new() + .add_message(execute_msg) + .add_attribute("action", "saas_set_max_votes_per_option") + .add_attribute("operator", info.sender.to_string()) + .add_attribute("target_contract", contract_addr) + .add_attribute("max_votes_per_option", max_votes_per_option.to_string())) +} + pub fn execute_set_vote_options_map( deps: DepsMut, _env: Env, diff --git a/contracts/api-saas/src/msg.rs b/contracts/api-saas/src/msg.rs index e73bdbc1..8fb67a81 100644 --- a/contracts/api-saas/src/msg.rs +++ b/contracts/api-saas/src/msg.rs @@ -106,6 +106,12 @@ pub enum ExecuteMsg { contract_addr: String, vote_option_map: Vec, }, + // Proxy for the amaci round's SetMaxVotesPerOption (admin-only on the + // target round, only allowed before voting starts there). + SetMaxVotesPerOption { + contract_addr: String, + max_votes_per_option: Uint256, + }, // Proxy vote/deactivate on behalf of users (SAAS contract covers message fees from its balance) PublishMessage { diff --git a/contracts/api-saas/ts/ApiSaas.client.ts b/contracts/api-saas/ts/ApiSaas.client.ts index 370ec0ce..bdbef932 100644 --- a/contracts/api-saas/ts/ApiSaas.client.ts +++ b/contracts/api-saas/ts/ApiSaas.client.ts @@ -203,6 +203,18 @@ export interface ApiSaasInterface extends ApiSaasReadOnlyInterface { memo?: string, _funds?: Coin[] ) => Promise; + setMaxVotesPerOption: ( + { + contractAddr, + maxVotesPerOption + }: { + contractAddr: string; + maxVotesPerOption: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; publishMessage: ( { contractAddr, @@ -303,6 +315,7 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac this.updateFeeConfig = this.updateFeeConfig.bind(this); this.setRoundInfo = this.setRoundInfo.bind(this); this.setVoteOptionsMap = this.setVoteOptionsMap.bind(this); + this.setMaxVotesPerOption = this.setMaxVotesPerOption.bind(this); this.publishMessage = this.publishMessage.bind(this); this.publishDeactivateMessage = this.publishDeactivateMessage.bind(this); this.signUp = this.signUp.bind(this); @@ -571,6 +584,32 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac _funds ); }; + setMaxVotesPerOption = async ( + { + contractAddr, + maxVotesPerOption + }: { + contractAddr: string; + maxVotesPerOption: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_max_votes_per_option: { + contract_addr: contractAddr, + max_votes_per_option: maxVotesPerOption + } + }, + fee, + memo, + _funds + ); + }; publishMessage = async ( { contractAddr, diff --git a/contracts/api-saas/ts/ApiSaas.types.ts b/contracts/api-saas/ts/ApiSaas.types.ts index 9558e5f7..f534415d 100644 --- a/contracts/api-saas/ts/ApiSaas.types.ts +++ b/contracts/api-saas/ts/ApiSaas.types.ts @@ -73,6 +73,12 @@ export type ExecuteMsg = vote_option_map: string[]; }; } + | { + set_max_votes_per_option: { + contract_addr: string; + max_votes_per_option: Uint256; + }; + } | { publish_message: { contract_addr: string; diff --git a/packages/sdk/src/libs/contract/contract.ts b/packages/sdk/src/libs/contract/contract.ts index e2b4eb08..63a21540 100644 --- a/packages/sdk/src/libs/contract/contract.ts +++ b/packages/sdk/src/libs/contract/contract.ts @@ -160,6 +160,17 @@ export class Contract { }); } + /** + * Query the round's per-option vote weight cap. Returns "0" (as a decimal + * string, matching the contract's Uint256 encoding) when no limit is set. + */ + async getMaxVotesPerOption({ contractAddress }: { contractAddress: string }) { + return this.withRetry(async (rpcEndpoint) => { + const client = await createAMaciQueryClientBy({ rpcEndpoint, contractAddress }); + return client.maxVotesPerOption(); + }); + } + async isApiSaasOperator({ signer, operator }: { signer: OfflineSigner; operator: string }) { return this.withRetry(async (rpcEndpoint) => { const client = await createApiSaasClientBy({ @@ -368,6 +379,54 @@ export class Contract { }); } + /** + * Update the per-option vote weight cap (max_votes_per_option) of an amaci + * round via the api-saas proxy. Same restriction as setApiSaasMaciRoundInfo: + * the target round only accepts this call from its admin and only before + * voting starts (max_votes_per_option is baked into the process circuit's + * packedVals, so it can no longer change once voting begins). + */ + async setApiSaasMaciRoundMaxVotesPerOption({ + signer, + contractAddress, + maxVotesPerOption, + gasStation = false, + fee = 1.8 + }: { + signer: OfflineSigner; + contractAddress: string; + maxVotesPerOption: string | number; + gasStation?: boolean; + fee?: StdFee | 'auto' | number; + }): Promise<{ txHash: string }> { + return this.withRetry(async (rpcEndpoint) => { + const signingClient = await createContractClientByWallet(rpcEndpoint, signer); + const [{ address }] = await signer.getAccounts(); + + const msg = { + set_max_votes_per_option: { + contract_addr: contractAddress, + max_votes_per_option: maxVotesPerOption.toString() + } + }; + + const executeMsg: EncodeObject = { + typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract', + value: { + sender: address, + contract: this.apiSaasAddress, + msg: toUtf8(JSON.stringify(msg)), + funds: [] + } + }; + + const granter = gasStation ? this.apiSaasAddress : undefined; + const stdFee = await resolveFee(signingClient, address, [executeMsg], fee, granter); + const txHash = await signingClient.signAndBroadcastSync(address, [executeMsg], stdFee); + return { txHash }; + }); + } + async addApiSaasOperator({ signer, operator, diff --git a/packages/sdk/src/libs/contract/ts/AMaci.client.ts b/packages/sdk/src/libs/contract/ts/AMaci.client.ts index 9c8f45b8..f44c542b 100644 --- a/packages/sdk/src/libs/contract/ts/AMaci.client.ts +++ b/packages/sdk/src/libs/contract/ts/AMaci.client.ts @@ -404,6 +404,16 @@ export interface AMaciInterface extends AMaciReadOnlyInterface { memo?: string, _funds?: Coin[] ) => Promise; + setMaxVotesPerOption: ( + { + maxVotesPerOption + }: { + maxVotesPerOption: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; signUp: ( { amount, @@ -550,6 +560,7 @@ export class AMaciClient extends AMaciQueryClient implements AMaciInterface { this.setRoundInfo = this.setRoundInfo.bind(this); this.updateRegistrationConfig = this.updateRegistrationConfig.bind(this); this.setVoteOptionsMap = this.setVoteOptionsMap.bind(this); + this.setMaxVotesPerOption = this.setMaxVotesPerOption.bind(this); this.signUp = this.signUp.bind(this); this.startProcessPeriod = this.startProcessPeriod.bind(this); this.publishDeactivateMessage = this.publishDeactivateMessage.bind(this); @@ -632,6 +643,29 @@ export class AMaciClient extends AMaciQueryClient implements AMaciInterface { _funds ); }; + setMaxVotesPerOption = async ( + { + maxVotesPerOption + }: { + maxVotesPerOption: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_max_votes_per_option: { + max_votes_per_option: maxVotesPerOption + } + }, + fee, + memo, + _funds + ); + }; signUp = async ( { amount, diff --git a/packages/sdk/src/libs/contract/ts/AMaci.types.ts b/packages/sdk/src/libs/contract/ts/AMaci.types.ts index 50a78038..2686c05d 100644 --- a/packages/sdk/src/libs/contract/ts/AMaci.types.ts +++ b/packages/sdk/src/libs/contract/ts/AMaci.types.ts @@ -99,6 +99,11 @@ export type ExecuteMsg = vote_option_map: string[]; }; } + | { + set_max_votes_per_option: { + max_votes_per_option: Uint256; + }; + } | { sign_up: { amount?: Uint256 | null; diff --git a/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts b/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts index 370ec0ce..bdbef932 100644 --- a/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts +++ b/packages/sdk/src/libs/contract/ts/ApiSaas.client.ts @@ -203,6 +203,18 @@ export interface ApiSaasInterface extends ApiSaasReadOnlyInterface { memo?: string, _funds?: Coin[] ) => Promise; + setMaxVotesPerOption: ( + { + contractAddr, + maxVotesPerOption + }: { + contractAddr: string; + maxVotesPerOption: Uint256; + }, + fee?: number | StdFee | 'auto', + memo?: string, + _funds?: Coin[] + ) => Promise; publishMessage: ( { contractAddr, @@ -303,6 +315,7 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac this.updateFeeConfig = this.updateFeeConfig.bind(this); this.setRoundInfo = this.setRoundInfo.bind(this); this.setVoteOptionsMap = this.setVoteOptionsMap.bind(this); + this.setMaxVotesPerOption = this.setMaxVotesPerOption.bind(this); this.publishMessage = this.publishMessage.bind(this); this.publishDeactivateMessage = this.publishDeactivateMessage.bind(this); this.signUp = this.signUp.bind(this); @@ -571,6 +584,32 @@ export class ApiSaasClient extends ApiSaasQueryClient implements ApiSaasInterfac _funds ); }; + setMaxVotesPerOption = async ( + { + contractAddr, + maxVotesPerOption + }: { + contractAddr: string; + maxVotesPerOption: Uint256; + }, + fee: number | StdFee | 'auto' = 'auto', + memo?: string, + _funds?: Coin[] + ): Promise => { + return await this.client.execute( + this.sender, + this.contractAddress, + { + set_max_votes_per_option: { + contract_addr: contractAddr, + max_votes_per_option: maxVotesPerOption + } + }, + fee, + memo, + _funds + ); + }; publishMessage = async ( { contractAddr, diff --git a/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts b/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts index 9558e5f7..f534415d 100644 --- a/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts +++ b/packages/sdk/src/libs/contract/ts/ApiSaas.types.ts @@ -73,6 +73,12 @@ export type ExecuteMsg = vote_option_map: string[]; }; } + | { + set_max_votes_per_option: { + contract_addr: string; + max_votes_per_option: Uint256; + }; + } | { publish_message: { contract_addr: string; From e137ef97005b4aacca4953240b977800ffbdf1ee Mon Sep 17 00:00:00 2001 From: 99Kies <1290017556@qq.com> Date: Tue, 21 Jul 2026 18:51:33 +0800 Subject: [PATCH 4/6] feat: support max_votes_per_option in api-saas SDK path and expose it on created_round event - sdk: createApiSaasAmaciRound now forwards max_votes_per_option to the contract, matching createAMaciRound - amaci: InstantiationData reply payload now reports max_votes_per_option back to Registry (Option + serde default for backward compatibility with older amaci code IDs) - registry: reply_created_round now emits a max_votes_per_option attribute (defaults to "0") so indexers can pick it up on round creation --- contracts/amaci/src/contract.rs | 1 + contracts/amaci/src/msg.rs | 7 +++++++ contracts/registry/src/contract.rs | 10 ++++++++++ packages/sdk/src/libs/contract/contract.ts | 2 ++ packages/sdk/src/libs/contract/types.ts | 2 ++ 5 files changed, 22 insertions(+) diff --git a/contracts/amaci/src/contract.rs b/contracts/amaci/src/contract.rs index 8c3dd943..5934d9ac 100644 --- a/contracts/amaci/src/contract.rs +++ b/contracts/amaci/src/contract.rs @@ -711,6 +711,7 @@ pub fn instantiate( // Unified MACI Configuration voice_credit_mode: msg.voice_credit_mode.clone(), registration_mode, + max_votes_per_option: Some(max_votes_per_option), }; let mut attributes = vec![ diff --git a/contracts/amaci/src/msg.rs b/contracts/amaci/src/msg.rs index c0a257ee..4032199a 100644 --- a/contracts/amaci/src/msg.rs +++ b/contracts/amaci/src/msg.rs @@ -411,4 +411,11 @@ pub struct InstantiationData { // Unified MACI Configuration (for Registry tracking) pub voice_credit_mode: VoiceCreditMode, pub registration_mode: RegistrationMode, + + // Per-option vote weight cap (None/0 = no limit). Reported back to the + // Registry so the `created_round` event can index it. Option + serde(default) + // keeps this backward compatible with older amaci code IDs whose reply data + // doesn't include this field. + #[serde(default)] + pub max_votes_per_option: Option, } diff --git a/contracts/registry/src/contract.rs b/contracts/registry/src/contract.rs index 84235931..97a5a593 100644 --- a/contracts/registry/src/contract.rs +++ b/contracts/registry/src/contract.rs @@ -741,6 +741,16 @@ pub fn reply_created_round( "deactivate_enabled", &amaci_return_data.deactivate_enabled.to_string(), ), + // Per-option vote weight cap (0 = no limit). Always emitted so indexers + // can distinguish "no limit" from "attribute absent" (older rounds that + // predate this feature are indexed with a default of "0" client-side). + attr( + "max_votes_per_option", + amaci_return_data + .max_votes_per_option + .unwrap_or_else(Uint256::zero) + .to_string(), + ), ]; if amaci_return_data.round_info.description != "" { diff --git a/packages/sdk/src/libs/contract/contract.ts b/packages/sdk/src/libs/contract/contract.ts index 63a21540..15d80b99 100644 --- a/packages/sdk/src/libs/contract/contract.ts +++ b/packages/sdk/src/libs/contract/contract.ts @@ -517,6 +517,8 @@ export class Contract { }, voice_credit_mode: params.voiceCreditMode, vote_option_map: params.voteOptionMap, + max_votes_per_option: + params.maxVotesPerOption !== undefined ? params.maxVotesPerOption.toString() : null, voting_time: { start_time: (BigInt(params.startVoting.getTime()) * 1_000_000n).toString(), end_time: (BigInt(params.endVoting.getTime()) * 1_000_000n).toString() diff --git a/packages/sdk/src/libs/contract/types.ts b/packages/sdk/src/libs/contract/types.ts index 51bc3fd3..04f7707e 100644 --- a/packages/sdk/src/libs/contract/types.ts +++ b/packages/sdk/src/libs/contract/types.ts @@ -35,6 +35,8 @@ export type CreateApiSaasAmaciRoundParams = { deactivateEnabled: boolean; registrationMode: RegistrationModeConfig; voiceCreditMode: VoiceCreditMode; + /** Per-option vote weight cap enforced by the circuit. Omit or "0" = no limit. */ + maxVotesPerOption?: string | number; gasStation?: boolean; fee?: StdFee | 'auto' | number; } & CreateRoundParams; From 975e26265cfb8952e29ad24800374ae20dffdd4f Mon Sep 17 00:00:00 2001 From: 99Kies <1290017556@qq.com> Date: Wed, 22 Jul 2026 18:58:04 +0800 Subject: [PATCH 5/6] chore: upgrade circuit artifacts from v5 to v6 - Update vkeys for both 2-1-1-5 (test) and 9-4-3-125 (production) circuits in contracts/amaci/src/circuit_params.rs - Sync vkeys and zkeyUrl (v5 -> v6) in packages/cli/src/core/circuits.ts, update SHA256 hashes for both tar archives - Update S3 download URLs and internal tar paths (v5 -> v6) in e2e/scripts/downloadZkeys.ts and packages/circuits/ts/generate-logs.ts - Refresh e2e/circuits/vkeys-amaci-2-1-1-5.json with v6 vkey values - Regenerate logs.json for amaci and registry contract tests --- contracts/amaci/src/circuit_params.rs | 20 +- contracts/amaci/src/test/amaci_test/logs.json | 172 +++++++++--------- .../registry/src/test/amaci_test/logs.json | 172 +++++++++--------- e2e/circuits/vkeys-amaci-2-1-1-5.json | 10 +- e2e/scripts/downloadZkeys.ts | 12 +- packages/circuits/ts/generate-logs.ts | 58 +++--- packages/cli/src/core/circuits.ts | 32 ++-- 7 files changed, 238 insertions(+), 238 deletions(-) diff --git a/contracts/amaci/src/circuit_params.rs b/contracts/amaci/src/circuit_params.rs index e342c387..a88c97d7 100644 --- a/contracts/amaci/src/circuit_params.rs +++ b/contracts/amaci/src/circuit_params.rs @@ -44,7 +44,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), + vk_delta_2: "19b3324e99e392444b416f376b6c1985756f2ce27ba8001611844b7709851c86076765c63f2a1ad176699fd24fab90f4a9fd10b7d934e73f168a892aeb8449b22048de2e2e86a887316a883b72b116c571aac32e2bb80fc875db2be20b4ce86e06d2c2711d7f387ccc6eacb5883ecfc78c729d37cf9970909b47b161f14b5763".to_string(), vk_ic0: "2109d20e2dfb65b2564cdd873f95f21a9215d9757c6ec62637b8d80373e1e9bb066ef0037b411d062439a5034b5c71bcdc2df0e3999fe5b7afd7cb88a32ceb30".to_string(), vk_ic1: "05199f9ffa6b1ec953808a3dd750ad9168ae7a1464ddcead6cf31d61530e22a215b34e716a4871c189f25cf43ebc656d3256812cb98179183df2a9da65da34b9".to_string(), }; @@ -54,7 +54,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), + vk_delta_2: "2747cb292b1263b86b325ae591e1e226049404334bb09165c6a7efac9744178b22508dbdabea8802179f8f2b7c9d064ab962fe834c16738721d03ad6db6836f9090497dc22da1e7959e91b42bba33f2b74c9f0c2a4a21055a7148b6716fb95e629bdc0b0b474b84c6e41687154ec37b95ccaed7d1a578fef1873dcc5e672d912".to_string(), vk_ic0: "0b20a7584a8679cc6cf8e8cffc41ce9ad79c2cd0086214c3cb1af12146916bb9185b916c9938601b30c6fc4e7f2e1f1a7a94cb81e1774cb1f67b54eb33477e82".to_string(), vk_ic1: "081919adecf04dd5e1c31a3e34f8907d2ca613df81f99b3aa56c5027cd6416c201ddf039c717b1d29ecc2381db6104506731132f624e60cc09675a100028de25".to_string(), }; @@ -64,7 +64,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), + vk_delta_2: "26f85af9fdc3df0a5ee4a7737e629eb22e1df46aea9c67767eb1c9fa16387a6b1e00017122d8106b5967c49f2e976cec95fdb80aeefd901e808e01c314963e771d7773994f156c2092b98f0e69c2987defa8c338b2e0f3dbe45d78112306782a07227a53bcb6ad9a60b84924da88f13275a9a4f29843b06bf89b2f072b6ab6a6".to_string(), vk_ic0: "141ed95aed8eac95334e6dbaa513736949402fd820920d8e2179d7be54593f60070ffd76988c62dbf2cf4a365da0fbecde7e7ccb39f1e0e0728a6941da3435cd".to_string(), vk_ic1: "2c1289b05f9093a1d4c7536093702b08d57654fae20ae871de2598565c43c8611d5bc6caad360c2b6f68480aa71efbcc506524104152bb73f79d9cb0f3d12180".to_string(), }; @@ -74,7 +74,7 @@ fn vkeys_2_1_1_5() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), + vk_delta_2: "07b9d5bf21365da183856ac35153c99e3778211de334e7dc31db2cd038cb3f84009c65360ff6b5581f7ef5ef43db9ce552ab6a085ed584e1c403a913d320f15c0fe6dbb6aba6461d43b49f4e3dca84aba1564e72bf6d9542e75fd6677834a9611b5c161cc38da933e6e4fb6ef58f5d4e04c19b6df7cab0c650b6c4d572ef5789".to_string(), vk_ic0: "29639aea06acd9b07e36d2456153d4e81581d65efb2fc93f0d54618398be1c471f49496bce6f344badecd9493d07faaaa2d09c7216734488f3ce2e2d0bd25be9".to_string(), vk_ic1: "20ccb32cbbbb10099ab8ef2bfd196ec22b3c07c8c7eba7076bb8d16be4aa69ad0b0ff4e2a298219ef216024cd65a8b26470a7daa2e8ce55af41038a74d5d589f".to_string(), }; @@ -94,9 +94,9 @@ fn vkeys_9_4_3_125() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "1ca282bdb2bf70aeae2a394515a6b090972b172f2baa302c9c4a5e2e62044085172b006b637672503a9ad454148c20024cc3412cd3af07fdc172cbeec61de5252e7f42a023bce7df1c2b9bb817d5c6345e03462f2231ef0b4057c487da87e4fa1df5a5ff810e7c9f18acf76a9ef37ed89169f54af3326f63e5c732886b57b0d0".to_string(), - vk_ic0: "0f4ca042d9df017c2277a5348138072354637d7a548ed2432a62b22bd6b0793c14d190e06d249c579f2f3cb9c0d8e5223798931ac8fc645efc96739d34e3a553".to_string(), - vk_ic1: "0231a17b99604840a6870d1c5ba31394ceb6683af703d083338c30bdb87b88851283ec802a494552bd00732fa61bfc619a4238a0ab6659e5c8fa91b2a5e5143b".to_string(), + vk_delta_2: "059756653a474da0d3a99522bfba92428ff603c8254e3c5016c41fc532baadd42f456e58a452cc9ace1828ca8eafcda8685872703c35ef5d796e7e8bed5a4d00002d372c4d2bbccad47dbed288eaad7a6bce92f605f1082fa4442cf7555b6dff14eea0b33c1832a169e2e42dcb07749d88806193280fd009912ab35af8b2a2c2".to_string(), + vk_ic0: "2936807506628c01f5c320b0cfe38bcd7de3f1c9f78649cb2ee9fe835c523e602d716f08d8b98a688c9f106bb18060c66feaf31854327cf20dd3170a284f8258".to_string(), + vk_ic1: "0db49219818833defe6729fe69d23bbbd6c892b45b49792b798c13ff3ab72f3e1674142a207b3a01330a307e9613dc643b181a728bc4a041ad5a0ff37900c71c".to_string(), }; let groth16_process_vkeys = format_vkey(&groth16_process_vkey)?; @@ -104,7 +104,7 @@ fn vkeys_9_4_3_125() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "232a958bbc349f1fa27cf560c9efa7248aa95d954de64a3e170c2abe8265386529255f7c77a1a70b4237d6fa8763c64699c3d1eb62a54e60349cb32c850ef1b10044d8b3fc7298d54a097453c9a9b62442fa3851e2c1dc582c47b9d60e0a62392ca45e26a1793a485d1e8c81de124d2b1cf2afefa69459ef7d567076bc864dec".to_string(), + vk_delta_2: "04ac819540c297e090f7798b260dedf91d7d07e0c28c935b1727e815fc0b690a04c5daab1db9d8cf8dd34f682d74f9cc692ad4c48402aad88c0071769e13b589013d75b834c55ff9b9f9d3dd8b2c736b836af659800f6b1b0b1602f3c6007add2d1fe9bebad5ca5847b53d2241fbf84c32ed836b3226136a213236fac682561b".to_string(), vk_ic0: "1840e9af4d2094c190adf2e40468515ee760858a2a41a26aa7916bc38bd7ba9f01ea24bf4adad4d679ddf5858dbcb4587b954a6062b264288f6e191c6d697759".to_string(), vk_ic1: "1ed068e3bbc130b6a420efe22b7f26b7372686108ff1935eea7508eb814d3e2e0ab2da2095988387330108bee8d58121be18e61bb594ba9b8982a290cfc2571b".to_string(), }; @@ -114,7 +114,7 @@ fn vkeys_9_4_3_125() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "11e969c11af8421c1474c478725abee854af14412b35f69010f5c9913c9eb9401474968c8c1608ebdfb978f7e72380d046d1ac079a64bae0fef5052137ae829d07317efdfe94d826337c8225c7e78be3775f3dd61a60486fe32ca7587223c58323534bc421de3812160299521a2670b43351d8c6ef3a3204ab9394c05111f805".to_string(), + vk_delta_2: "147cbe7e7451633254d01f220cf3521717258300cbe8eea7f9c5e4a5aa776a5d1fbe926fe9c14bf755a9c2ac403e2c94eaf9015dda20644279d115e9b8556904205164034510b8e0dbad7647a37b4d958247ac849463e291152460f3cc08cd3c2eeb4a102cd303af7fd64bf0d61319f658330f121373b9b5b983c2e680ba3d8d".to_string(), vk_ic0: "2341ef299bd50b06e3885f2c95e6e043ac4a9b30263fb5b212b9c5ee443ab28d17b0dd121483ee7a280fe8a82384e8bbd0e52c32be97148dfaecb953ee0b34fe".to_string(), vk_ic1: "04c3cdc1e32f4e6eae21adb419ed037dcd5daa9012bc9fe31e4ebedba31c101b00f8483d686d64d0eb7d1c3278b4409f4717dea169970f62505a52e3c08b6d4d".to_string(), }; @@ -124,7 +124,7 @@ fn vkeys_9_4_3_125() -> Result { vk_alpha1: "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926".to_string(), vk_beta_2: "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8".to_string(), vk_gamma_2: "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa".to_string(), - vk_delta_2: "1c94083c2b90d4f41d7e83000647860bb278e98705f0c9553b790ba4556d88451b2e0741e3cba46801412cff620bb191ab358604fff432bf073a325c9f19a1860cb0286d5261f5e0214f11320d740fee711f78575a8f3b47bebecad7e16a301c0b0d80535eb8f30fd18c2627e9f08d1b1bf3f7210994465489722587bba1487f".to_string(), + vk_delta_2: "0eb06f2f1b513f042895affc86f337c896aff1a9b0b158bbd3608ba3f27165862c47682ba5c8ebad4178c520f9d88e9bfa8cadf098baf2fe5509929131f909741d6888dd7e2462f4e7d0564ace9128facc836d221dff6c0b85181519ee039f2b04f70b9050f84fb9ca004fd086fab7ca49c9c07e32b841805147aa86930fdb9e".to_string(), vk_ic0: "0eb39e5aa053d6676afa84d88c23996669b18eda44eb6d97420176ff55c276290ae7df9c85d77b9aef313093fdeada3c53cd1b0cfd7ed04460a719cfff4e5925".to_string(), vk_ic1: "200467c396f31ec6b2f3324d5fa38a28e18ce24c1a92742486553e2375204fc82e4feff4af5e2c2ac4acd05af4a64d161edee15e1feef61d2f4977860643c94b".to_string(), }; diff --git a/contracts/amaci/src/test/amaci_test/logs.json b/contracts/amaci/src/test/amaci_test/logs.json index 8c9b9b87..246e703a 100644 --- a/contracts/amaci/src/test/amaci_test/logs.json +++ b/contracts/amaci/src/test/amaci_test/logs.json @@ -25,20 +25,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "10199538548927120714932940033352720386974078405513490410706428349310392875182", - "13655872631808810427644409650428422335240746202781882618915838707176748177032", - "4522510631409687676287452827143364603161458319387795781089857236379245124620", - "12631360558122316932395977841092807384254788197434707521393446594481440406888", - "5064455035049685748075782645836256439144373654497265984503385954053756719991", - "4949918418208276018510186207756754181199761410148368199846220358869622265113", - "5133442886621740816906245138693327457584430710691836383349337725304320983752", - "21742787944525354780732770859294263180265728165218559055149235794885028481475", - "19422152523225351173772773148035207096795669433417888803696755744763175112484", - "10819561521219992066365168346219236906024782170984835580367633443988113374742" + "11987553928740803634417663512635253855268235019287090864522096909601222635820", + "1126757259584068823522931213558329477987959817434970103527814151007371134313", + "2193897290440096321924606354830955519464836460550140669852141235714478873858", + "5834739755542647121213107019054569279290787522241935696336403201060035633763", + "15230282765022695072600822535925765574636510805782468007088736878342996956286", + "19995808609248648087420841094850186356500548774027743435617150703871044071751", + "570383390330472735354184483238583241201971442292422556814951629159679361868", + "19087599719028251488999351467596544581471241660606127105625569316593996497335", + "13959936213573774549747238960290239028241190321725674543956625154090155174043", + "21603236421411974432775557010565214620975908199554652347078833457283225095097" ], "encPubKey": [ - "8338997010971674380540897807518105678225073705648002510933270265809332194034", - "13954517998564222966059351125502869538349466448160605276291359530546041450223" + "7616154665494324701490174814194233741403699149223537970070387907111185491211", + "2300395638254881950136381118604829987618336087803616041336612622763065745523" ] } }, @@ -46,20 +46,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "21413339661421681364812790641898829049904718437636946307217227781082821973592", - "20866556127828344449917046633348352053125043790470431083597009723576339931172", - "8635053267067632405674900512529287999708821487476410722585604545612226454061", - "5695656229573187806439006959232123033670721187477559694603050772103462573924", - "12050486414260508422380213600501293647005530392590103757769436495303699792315", - "6109464031463685437699832946297413880643404513610789419211882541091402968519", - "13237072433322268487406531470690349764086173953414719991950588721660354999372", - "12030953900314540795016119474423496015821661692373799828494139055880859538321", - "20588181222708073166756414028925379895453337390525906764143801049941065230189", - "2806495032912144929978846495374342223921156224156462179036151703131574152213" + "21311386309501895287144104756656184736854485316078500440790734303714056861079", + "1150877314545339727615793924449783096979294201917102298503300413756473145743", + "6162041292928380914023937558959956577111776657195479393150682469899456696952", + "20910926021597410483528673089368411303267644810764205621401762318374646802454", + "7406082419448787252206802590610059640558947062587778755706708281138602581182", + "5872977136960673881730744897049389941662068227685629270623669403307901026796", + "7595969704280085325587350692144530355156466328851060456871222479949641134150", + "8299612858453347711324348414867835457976319943735701142546576602090620215593", + "1148264455643015282572219441402622267407142113393104487967816376333025528987", + "8031072769661254486504110041502739949059022580329532146294357426400250537169" ], "encPubKey": [ - "14790633911774005825263096161370523514919388824876132387568629307861038175119", - "12920696696847634835141935547586976377793376302885926386553774258531479916623" + "12242444805422065058859366142813193728547127247989786742830738670683907966275", + "9310565587342035791618756521052260362409520296247445468922380538585701857373" ] } }, @@ -67,9 +67,9 @@ "type": "proofDeactivate", "data": { "proof": { - "pi_a": "06ef627c054aa4c83452b8fa5d7fb84840b9640f729261c3b63c4ce3cea1037c1cd9cba65300a8ae45ff75d496c61dca09e6a5bccad88658d98d3dd7d066d851", - "pi_b": "068abb620a55a7f30929a57a33073ac4ec48079410b1907b495a68f6226d46ae1636511c5eb0d992bf73738dae4b1a5a5e35acb3b3cb4ca94699e4c77281bdb11460c9658ce22731754c24e002834879cd1fac35795036bccaa1cb0cc624d2c81169629d21bfedae1ccaf6a73caff2dfb9eda1ed28e740c94c58662d48643514", - "pi_c": "1f64bdfd5a9d89f5b9e8d07576545fdd86833de1b18d8352064f4a5d71c8f158125a99f2c645bdaf1e503d711c6a6430e5bd989acb794e16b611380cb30b9ab4" + "pi_a": "026395c195b9d652aa5c0de3939f2947f6746d11cf5a870f1b6dcd18a2f181de0f4805b4d8a6d34a08157453f71029f000b79530a5ac2aaaafc7af4346b3571f", + "pi_b": "1679ad22d5b22204ea73e733064b803ba92cf12c4b11de87b0702b9abd99a0302057d850f3a4543302cefd8b053f4370cce3bec2f69a40d1c06d41334877a5292adaff9015ceab45d0d227fc0a64aaf266980fb62ba132d1175f88b803e05eed004051c12f037b0fab2ed5b8cac4fa67e8637a1067afdc90f10b155cadba9fb8", + "pi_c": "0b408842fa62db8d68d2c891661700e8a8acef40fb7b73ad0b7fa65a9036e99500d263f32e0566f524e205a2b5f04cf3b535ac678fbda99ee7baa4c433712a3a" }, "size": "2", "newDeactivateCommitment": "16594648813117521549607651409199825676087230774332331178259600792935825001695", @@ -79,7 +79,7 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "10641036700368614459615677103397157737551724537581240700605661156499962601134", + "2135675472755628548045917528376933133598785546627538233990634886233015710737", "11130071843769412659933467398663901612334403299453766868287010509469499313889", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "9822028196133927497745238851722523433315624887764435741027677520879911614812", @@ -105,15 +105,15 @@ "20437799137966928537540131352831724208517012039281435330961519441894644714811" ], "proof": { - "pi_a": "15d7628548f9c805ed969b15fa977108db741e15435d3e5942774a813d4b7b590d503f7210c274ffb5536eb6a10e0eeeca53341089e5f28457e4c37e31812c40", - "pi_b": "229b8fa828fbeae3b8984e87bbf2a1956d0aeaff6eb27b805f0c81f8414807a117294665f6af32083d17aba75078d8387c7ce3dd7e7f00247b0544c46f26a697163145e7b75b52ed6d3b9b52b3b8399345bd783b7ff7d7a45e248735b32b63fe2d6c752356728bb97eb531849cc8e894e8a2d930210d300a20cbd4184c9fae6d", - "pi_c": "28ae0a1c52f015dac0a6c2ab765b1ef0585b2a8b8e3198b3e1f2b0ffbcb80d4c0f19fa28289b657c14ddbf6e504ef431ca6cd7aa9f49297809ee09d462da5ee4" + "pi_a": "20a7c2a27827320a0215be575b50361ee2562c21bfc5804f8f8dd5027666dff601719fcb1e6e208f25e9c9856cb6a25506761fa94a3910fe3606b2babd355060", + "pi_b": "1b590527e28e6f53da43c8fe3a7c7d42f065589031579cec5eefb0e8dccbd4f9042f54043a6c7464cb691fac119c5e247555be691ee7ff1cc78a319fbb4bc6440c1a00b7db45dcbbfb2a0af693a4d72a6b8d44fa74335ada52e849ae3955e03a0fb8fbadb1ff62ef9e0c5f769fcca25172f7d4a68516fa5f4324bb99c0fc7661", + "pi_c": "225f807ddd0fddeba8f9da47e9c06327e5da17ab51c1bbaa1c46fe2401d24c100026ad9172e9df72210308fb2c8e843a8b488989c9bee7ca3bd4536a5a7078bf" }, "d": [ - "10429275752581465043716743428927652264952855894921267050669121213403906525022", - "5229928821704293629422300883038551475821805973425538223807642872731614682747", - "12584624188331812056728058433134688487689081239749498128311790830626561180785", - "9554480257957972556963874295494677102261600637704276946797523829472465658661" + "3990565883802197547614032828563098913972310621233644053890408156473641405662", + "20975886446990093378538432591986295780521836768857818608253463865069223649840", + "13402874431046659486648092864757633586198566164088652626750529029784352521103", + "20273874782642234532761353535959516203634373343738763612614213573739424005638" ], "nullifier": "11275217544102381393112296424037264033603560840958598162766803219699297021995" }, @@ -121,30 +121,30 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "11275217544102381393112296424037264033603560840958598162766803219699297021995", - "10429275752581465043716743428927652264952855894921267050669121213403906525022", - "5229928821704293629422300883038551475821805973425538223807642872731614682747", - "12584624188331812056728058433134688487689081239749498128311790830626561180785", - "9554480257957972556963874295494677102261600637704276946797523829472465658661" + "3990565883802197547614032828563098913972310621233644053890408156473641405662", + "20975886446990093378538432591986295780521836768857818608253463865069223649840", + "13402874431046659486648092864757633586198566164088652626750529029784352521103", + "20273874782642234532761353535959516203634373343738763612614213573739424005638" ] }, { "type": "publishMessage", "data": { "message": [ - "1791680339236253889870974892742243504774453269866464278763091344014289183583", - "12912656003372824590342609694634798852678099940841567149859709770499934884335", - "18791018738860930723859857404737068756536348601057408596997912519625044543281", - "16584393316295443194801986221520890994492417484962308885046757915488186492538", - "10667420618487120661693041221680953120443615201158787705620484935765005559184", - "6083096472073668943522615658350531348879717470376415651153190268996804830829", - "7369335400032223970672086473473920997874197133330216122083652342087715654089", - "11076008935601220303260021284944519703873108079428411147338084895255352491011", - "12786284176937166464320672251025772023625536059394965982704532763666085546223", - "9007229654543442343208836150206963612011422402123778131650148326366616169094" + "19208706095555745143625695294672675890201420486926798885920651872354465141325", + "10085441150541315870648387992218790592043940397176696446861244079948793492364", + "20738268597064524755440909036964690205693798077008281951488631992192727358151", + "188533567704293283725497020050984074616077575225176000671834404611467650210", + "1204402262633908865091819298999689914506277801183701857622608568576304180989", + "10519129101995290655998575274686496456964027191949901301654265993291491494048", + "13487331948724235781221030347342297015411583615220436258015880416258759726843", + "12076666216781518345337885624002004619159281931405214396880725488589259413465", + "15670145422839531194390723276589155034086045383711141136257769981104544116150", + "14262734848066752401627254667766029456699818428618027000469328245138398741534" ], "encPubKey": [ - "15475608500420978206129166766118247249151489996252896147336817370649335541072", - "17790489522381535934163155608043378122485307312462592830426988610875473620439" + "1211328385135184320010501442895662388469577694193723999911417607813823320207", + "10749711694637601966243180944743203657875458682395828274596019358592644622697" ] } }, @@ -152,20 +152,20 @@ "type": "publishMessage", "data": { "message": [ - "2934286026199833719272274363447804657603644797607191690960611904679092494208", - "12686659491981967937885141550488300901190472917973423890635403564395400536901", - "7822555136442100122666187117646855225846556970307757521210899898820044437020", - "17114049849715767097782437560582426322864545681879971490785412509629340536949", - "14807269430265246696328008798735566109518374105362787944453596069680861518670", - "19122159091541582051084901704653445387383915132506412226090839918177930525077", - "6534696491684083090835559331095394062070656382177143005801725078565336692891", - "9152087624780184790158276476573072241077492398510162683728830438363124733227", - "20660863482905804982381708023290238625536550513031385627760316105386421306574", - "15773470826016432067698852442561603741738010247964917243277038599536143508214" + "8968811499879834488085432887406099691357930743597400149880937810826749432741", + "11977891043796389746045421212159926311898450542234053989773610600930178192502", + "281501121614525983147332396469790211438622488475565642771817627682333786249", + "9100690296533618537163841894198029205677888291172371260364134732546626310463", + "17078348491431788399049547734294131771700242734225590181886718352299443291281", + "21450855024302726954615445057753830575555877588307435182621475316838615124820", + "10900431809146694428437984204538994994941533606094380937477886391625037447755", + "3337610403873013432150329465374313865426811710058525646376487899609930044935", + "16975838084504452463625049352327190703683489087250269524779720608562445888965", + "12222878022475487026765301282205034869637157752928126522553249839015554021118" ], "encPubKey": [ - "3246882523858798579653725632245677815572520121562528893682828338364433544239", - "251469813163058146760472586440492200141935016615685184229967914227285567741" + "18259975963345091655295771101429179848868646725131880720996723303604339718656", + "5206464926271134880990760175082419984245432672636643876804180999092396504284" ] } }, @@ -173,20 +173,20 @@ "type": "publishMessage", "data": { "message": [ - "6040209671941422224396602067545041920520358782195834435128413473696786837333", - "19960515712904479693190879460799401141735713693858466758411443985892378422179", - "18684049546709024405268090451084859257331206297993892767152697777168105193950", - "4417067055532741121958645526962600415558295671361599386718254482151320751800", - "8831014646401085985422075959553401353474401368058172621332926526032482358682", - "19217537575108723326676749657287652803032945360366531731763213424659467783655", - "18251504118463383519769062943112898564880497948309370456680815597871817867538", - "2086572403656215063854110231912436577966018392734032815223971612619051390233", - "4272366053435368552491549023761060025938452467762466263138690546603872915203", - "8120048915061515603211575426724595332593895770922805744882866281921989790750" + "384250227423424524743846099778205647880644114582802178551330269838114721778", + "6253382015299972856524497041806156052556864278773142985948064749712905559502", + "16205791792813047282393356053487039168153248190904924903955519781454779876283", + "8685554755079599033002452121689287945936800899267232527425584678107093392863", + "21857625177109487443646306527455375318708753234213479019215597976515860125183", + "1952848269938869966639100223194813465560788632850430518767374721509422657793", + "11741436154878781580853915187761588177600873659343581133673892605600902177112", + "5441761344436874846527893802746954285974761152499377876611490803004466213195", + "2158698878360782841061341132300015245999077402680697269938377882544062777354", + "14960023789636385476729202648247712537855087267413555807395516220422619308149" ], "encPubKey": [ - "19756256018645496875540731296733822049290414734956005295678189287448357913848", - "2707256377586192612467480538754151266138587489076506164860615112668134194308" + "2651644058252294902748096819293778357120124143797762100365512287127713627783", + "13171185775754670120173402036455084014002333400824314941541104745026848345420" ] } }, @@ -194,19 +194,19 @@ "type": "processMessage", "data": { "proof": { - "pi_a": "2129ce4afbd1ef82ebfc1ab787c4347898badf204d996aff3774e6ad9c3bc0421f68466d74479415df9140b7e8dd10a3069eb4e164c90b28eb3b7bab5297d718", - "pi_b": "10030e86baf67dfa8fe66d6da6f4a5ba6b71b2ec4756a13b27dd6cb5ef9c1c651735599e35f6074a6b24c484ba7cc551f6d20f31297d52dfba49eb6d80b00e7006b424e0213d6e832fdd704937bcece614195390f55fbc19669ebe474709dbac0af047834f35a11bcfabead0e400338a17aa64fac9fa2c52e2d1bc917ef733ae", - "pi_c": "1e604286ffb13ff0b0bec30eb81e9829f02208e649e672cb8da38b134e672a282220a5ce7be897ff5f31ca6dc8f76b4ba7b0a86d5bd52a9584e79421d73853a7" + "pi_a": "1505458b94654d8ace2efe171a53a1c4848fb5c4e53e843ca97c679744139b511858b468a2c64483e60f74cfe2062da135256244a0b272e911a3123092605db6", + "pi_b": "1f8d3d347cefe5c8b5b5ce56df3a404504581011a331124bf2d6aa6e04f0c2c42cff1d2e36c7479463a002a85909e6282fa5ba0f472cc5abba64531ed8842498124b466e80f26cdfcc95bd7067ee8ebe3ea56561774be27ddb8142aa8c446579058b3ab9a024202a1dbef60de357b8788704b18053814e8cace253bf94add4bb", + "pi_c": "120c4db956e7b325e16b5af69b25e2e51d402ae620a05eb9da849a1dd7d9723a07e04ddfa8abd975e83e5f6f4067c38e2c053601d1fae610463df01981c667b0" }, - "newStateCommitment": "15747144277495644891688004720427985491197111452878407902812834851808276585502" + "newStateCommitment": "7294752578784620390539752279591063208389533968884488588996398432974900514322" }, "inputs": [ "18446744086594453509", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "526044335307134503491815026254278366672136736885761787302017270911568883596", - "6346528390895127279807599986474483438865420111586097124828966882255208009484", - "15747144277495644891688004720427985491197111452878407902812834851808276585502", + "7504625193227330538506566769358843157800673938191671210875712779760289416459", + "9227191193358443775699457971745319584512473689998474797530726497270008077098", + "7294752578784620390539752279591063208389533968884488588996398432974900514322", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "1" ] @@ -215,15 +215,15 @@ "type": "processTally", "data": { "proof": { - "pi_a": "1d4d31970050c6dd47346215fa67a04a8b0b171539ba662d1e6643a4a116aef22289120a6384615ad650d8482223f6925f18311d82aecf58acfaff3a252f1c02", - "pi_b": "1dda84bf5bef508fde174efefe91723c9fa37c37b1a9719f4ccff9272125facd2f26e1cbb10fa46afdc770e12687630b9b56234e94967a61ba2d70ddc76bf37f21de8517756f16fe243ec4ca1b63ef999f5e59e25c76b6ce275197b970581f7227ccbcb1352195eda09fb8322fdbc313660459dd0be0c4c92982f875fd0c445a", - "pi_c": "2bbfa115c59f51affef995e5d3bdc2d317c576c5e1b60bfc092b807926f827c9078076b42e48c997dc9c308a26bcd01136b55584688d951e0ae77e1afaa0ba83" + "pi_a": "1279511748a3392610261c74ef288417dee879fa8760de4e747106f49de3d86721692a916d5d8775f2dbb09b3f8f137652e4c71381f45506d38bfc6ddeaaf43a", + "pi_b": "1ff4b65e4676468c9e75c1d3fa19e4aa7b2ff401a586d81e5966b54d624ce5451306edb424d489354257c0800eecbe093ad0cd67d2dae157daf93633f13fa5c723d7b3e58560218aa0df717425fd51b55e7013ce6c93674236ba2f7f842d7ee61b420296facdd3dd627e38575be3a7c6caa15d02461d6604de7743b8311a884b", + "pi_c": "1b5d9df41158e4780cf2ffd36bf5cc20668adb112d607a3d3631398c06ebda5511725b4c35175403f09d78d39dece2c92931f1ae4b7998d2c2734fdd95c43681" }, "newTallyCommitment": "5119554139732678588072159140519209785192441754076468540607385260141479782116" }, "inputs": [ "12884901888", - "15747144277495644891688004720427985491197111452878407902812834851808276585502", + "7294752578784620390539752279591063208389533968884488588996398432974900514322", "0", "5119554139732678588072159140519209785192441754076468540607385260141479782116" ] diff --git a/contracts/registry/src/test/amaci_test/logs.json b/contracts/registry/src/test/amaci_test/logs.json index 8c9b9b87..246e703a 100644 --- a/contracts/registry/src/test/amaci_test/logs.json +++ b/contracts/registry/src/test/amaci_test/logs.json @@ -25,20 +25,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "10199538548927120714932940033352720386974078405513490410706428349310392875182", - "13655872631808810427644409650428422335240746202781882618915838707176748177032", - "4522510631409687676287452827143364603161458319387795781089857236379245124620", - "12631360558122316932395977841092807384254788197434707521393446594481440406888", - "5064455035049685748075782645836256439144373654497265984503385954053756719991", - "4949918418208276018510186207756754181199761410148368199846220358869622265113", - "5133442886621740816906245138693327457584430710691836383349337725304320983752", - "21742787944525354780732770859294263180265728165218559055149235794885028481475", - "19422152523225351173772773148035207096795669433417888803696755744763175112484", - "10819561521219992066365168346219236906024782170984835580367633443988113374742" + "11987553928740803634417663512635253855268235019287090864522096909601222635820", + "1126757259584068823522931213558329477987959817434970103527814151007371134313", + "2193897290440096321924606354830955519464836460550140669852141235714478873858", + "5834739755542647121213107019054569279290787522241935696336403201060035633763", + "15230282765022695072600822535925765574636510805782468007088736878342996956286", + "19995808609248648087420841094850186356500548774027743435617150703871044071751", + "570383390330472735354184483238583241201971442292422556814951629159679361868", + "19087599719028251488999351467596544581471241660606127105625569316593996497335", + "13959936213573774549747238960290239028241190321725674543956625154090155174043", + "21603236421411974432775557010565214620975908199554652347078833457283225095097" ], "encPubKey": [ - "8338997010971674380540897807518105678225073705648002510933270265809332194034", - "13954517998564222966059351125502869538349466448160605276291359530546041450223" + "7616154665494324701490174814194233741403699149223537970070387907111185491211", + "2300395638254881950136381118604829987618336087803616041336612622763065745523" ] } }, @@ -46,20 +46,20 @@ "type": "publishDeactivateMessage", "data": { "message": [ - "21413339661421681364812790641898829049904718437636946307217227781082821973592", - "20866556127828344449917046633348352053125043790470431083597009723576339931172", - "8635053267067632405674900512529287999708821487476410722585604545612226454061", - "5695656229573187806439006959232123033670721187477559694603050772103462573924", - "12050486414260508422380213600501293647005530392590103757769436495303699792315", - "6109464031463685437699832946297413880643404513610789419211882541091402968519", - "13237072433322268487406531470690349764086173953414719991950588721660354999372", - "12030953900314540795016119474423496015821661692373799828494139055880859538321", - "20588181222708073166756414028925379895453337390525906764143801049941065230189", - "2806495032912144929978846495374342223921156224156462179036151703131574152213" + "21311386309501895287144104756656184736854485316078500440790734303714056861079", + "1150877314545339727615793924449783096979294201917102298503300413756473145743", + "6162041292928380914023937558959956577111776657195479393150682469899456696952", + "20910926021597410483528673089368411303267644810764205621401762318374646802454", + "7406082419448787252206802590610059640558947062587778755706708281138602581182", + "5872977136960673881730744897049389941662068227685629270623669403307901026796", + "7595969704280085325587350692144530355156466328851060456871222479949641134150", + "8299612858453347711324348414867835457976319943735701142546576602090620215593", + "1148264455643015282572219441402622267407142113393104487967816376333025528987", + "8031072769661254486504110041502739949059022580329532146294357426400250537169" ], "encPubKey": [ - "14790633911774005825263096161370523514919388824876132387568629307861038175119", - "12920696696847634835141935547586976377793376302885926386553774258531479916623" + "12242444805422065058859366142813193728547127247989786742830738670683907966275", + "9310565587342035791618756521052260362409520296247445468922380538585701857373" ] } }, @@ -67,9 +67,9 @@ "type": "proofDeactivate", "data": { "proof": { - "pi_a": "06ef627c054aa4c83452b8fa5d7fb84840b9640f729261c3b63c4ce3cea1037c1cd9cba65300a8ae45ff75d496c61dca09e6a5bccad88658d98d3dd7d066d851", - "pi_b": "068abb620a55a7f30929a57a33073ac4ec48079410b1907b495a68f6226d46ae1636511c5eb0d992bf73738dae4b1a5a5e35acb3b3cb4ca94699e4c77281bdb11460c9658ce22731754c24e002834879cd1fac35795036bccaa1cb0cc624d2c81169629d21bfedae1ccaf6a73caff2dfb9eda1ed28e740c94c58662d48643514", - "pi_c": "1f64bdfd5a9d89f5b9e8d07576545fdd86833de1b18d8352064f4a5d71c8f158125a99f2c645bdaf1e503d711c6a6430e5bd989acb794e16b611380cb30b9ab4" + "pi_a": "026395c195b9d652aa5c0de3939f2947f6746d11cf5a870f1b6dcd18a2f181de0f4805b4d8a6d34a08157453f71029f000b79530a5ac2aaaafc7af4346b3571f", + "pi_b": "1679ad22d5b22204ea73e733064b803ba92cf12c4b11de87b0702b9abd99a0302057d850f3a4543302cefd8b053f4370cce3bec2f69a40d1c06d41334877a5292adaff9015ceab45d0d227fc0a64aaf266980fb62ba132d1175f88b803e05eed004051c12f037b0fab2ed5b8cac4fa67e8637a1067afdc90f10b155cadba9fb8", + "pi_c": "0b408842fa62db8d68d2c891661700e8a8acef40fb7b73ad0b7fa65a9036e99500d263f32e0566f524e205a2b5f04cf3b535ac678fbda99ee7baa4c433712a3a" }, "size": "2", "newDeactivateCommitment": "16594648813117521549607651409199825676087230774332331178259600792935825001695", @@ -79,7 +79,7 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "10641036700368614459615677103397157737551724537581240700605661156499962601134", + "2135675472755628548045917528376933133598785546627538233990634886233015710737", "11130071843769412659933467398663901612334403299453766868287010509469499313889", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "9822028196133927497745238851722523433315624887764435741027677520879911614812", @@ -105,15 +105,15 @@ "20437799137966928537540131352831724208517012039281435330961519441894644714811" ], "proof": { - "pi_a": "15d7628548f9c805ed969b15fa977108db741e15435d3e5942774a813d4b7b590d503f7210c274ffb5536eb6a10e0eeeca53341089e5f28457e4c37e31812c40", - "pi_b": "229b8fa828fbeae3b8984e87bbf2a1956d0aeaff6eb27b805f0c81f8414807a117294665f6af32083d17aba75078d8387c7ce3dd7e7f00247b0544c46f26a697163145e7b75b52ed6d3b9b52b3b8399345bd783b7ff7d7a45e248735b32b63fe2d6c752356728bb97eb531849cc8e894e8a2d930210d300a20cbd4184c9fae6d", - "pi_c": "28ae0a1c52f015dac0a6c2ab765b1ef0585b2a8b8e3198b3e1f2b0ffbcb80d4c0f19fa28289b657c14ddbf6e504ef431ca6cd7aa9f49297809ee09d462da5ee4" + "pi_a": "20a7c2a27827320a0215be575b50361ee2562c21bfc5804f8f8dd5027666dff601719fcb1e6e208f25e9c9856cb6a25506761fa94a3910fe3606b2babd355060", + "pi_b": "1b590527e28e6f53da43c8fe3a7c7d42f065589031579cec5eefb0e8dccbd4f9042f54043a6c7464cb691fac119c5e247555be691ee7ff1cc78a319fbb4bc6440c1a00b7db45dcbbfb2a0af693a4d72a6b8d44fa74335ada52e849ae3955e03a0fb8fbadb1ff62ef9e0c5f769fcca25172f7d4a68516fa5f4324bb99c0fc7661", + "pi_c": "225f807ddd0fddeba8f9da47e9c06327e5da17ab51c1bbaa1c46fe2401d24c100026ad9172e9df72210308fb2c8e843a8b488989c9bee7ca3bd4536a5a7078bf" }, "d": [ - "10429275752581465043716743428927652264952855894921267050669121213403906525022", - "5229928821704293629422300883038551475821805973425538223807642872731614682747", - "12584624188331812056728058433134688487689081239749498128311790830626561180785", - "9554480257957972556963874295494677102261600637704276946797523829472465658661" + "3990565883802197547614032828563098913972310621233644053890408156473641405662", + "20975886446990093378538432591986295780521836768857818608253463865069223649840", + "13402874431046659486648092864757633586198566164088652626750529029784352521103", + "20273874782642234532761353535959516203634373343738763612614213573739424005638" ], "nullifier": "11275217544102381393112296424037264033603560840958598162766803219699297021995" }, @@ -121,30 +121,30 @@ "1292069856877288066001748184549394348238925165671369079386882546096792068732", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "11275217544102381393112296424037264033603560840958598162766803219699297021995", - "10429275752581465043716743428927652264952855894921267050669121213403906525022", - "5229928821704293629422300883038551475821805973425538223807642872731614682747", - "12584624188331812056728058433134688487689081239749498128311790830626561180785", - "9554480257957972556963874295494677102261600637704276946797523829472465658661" + "3990565883802197547614032828563098913972310621233644053890408156473641405662", + "20975886446990093378538432591986295780521836768857818608253463865069223649840", + "13402874431046659486648092864757633586198566164088652626750529029784352521103", + "20273874782642234532761353535959516203634373343738763612614213573739424005638" ] }, { "type": "publishMessage", "data": { "message": [ - "1791680339236253889870974892742243504774453269866464278763091344014289183583", - "12912656003372824590342609694634798852678099940841567149859709770499934884335", - "18791018738860930723859857404737068756536348601057408596997912519625044543281", - "16584393316295443194801986221520890994492417484962308885046757915488186492538", - "10667420618487120661693041221680953120443615201158787705620484935765005559184", - "6083096472073668943522615658350531348879717470376415651153190268996804830829", - "7369335400032223970672086473473920997874197133330216122083652342087715654089", - "11076008935601220303260021284944519703873108079428411147338084895255352491011", - "12786284176937166464320672251025772023625536059394965982704532763666085546223", - "9007229654543442343208836150206963612011422402123778131650148326366616169094" + "19208706095555745143625695294672675890201420486926798885920651872354465141325", + "10085441150541315870648387992218790592043940397176696446861244079948793492364", + "20738268597064524755440909036964690205693798077008281951488631992192727358151", + "188533567704293283725497020050984074616077575225176000671834404611467650210", + "1204402262633908865091819298999689914506277801183701857622608568576304180989", + "10519129101995290655998575274686496456964027191949901301654265993291491494048", + "13487331948724235781221030347342297015411583615220436258015880416258759726843", + "12076666216781518345337885624002004619159281931405214396880725488589259413465", + "15670145422839531194390723276589155034086045383711141136257769981104544116150", + "14262734848066752401627254667766029456699818428618027000469328245138398741534" ], "encPubKey": [ - "15475608500420978206129166766118247249151489996252896147336817370649335541072", - "17790489522381535934163155608043378122485307312462592830426988610875473620439" + "1211328385135184320010501442895662388469577694193723999911417607813823320207", + "10749711694637601966243180944743203657875458682395828274596019358592644622697" ] } }, @@ -152,20 +152,20 @@ "type": "publishMessage", "data": { "message": [ - "2934286026199833719272274363447804657603644797607191690960611904679092494208", - "12686659491981967937885141550488300901190472917973423890635403564395400536901", - "7822555136442100122666187117646855225846556970307757521210899898820044437020", - "17114049849715767097782437560582426322864545681879971490785412509629340536949", - "14807269430265246696328008798735566109518374105362787944453596069680861518670", - "19122159091541582051084901704653445387383915132506412226090839918177930525077", - "6534696491684083090835559331095394062070656382177143005801725078565336692891", - "9152087624780184790158276476573072241077492398510162683728830438363124733227", - "20660863482905804982381708023290238625536550513031385627760316105386421306574", - "15773470826016432067698852442561603741738010247964917243277038599536143508214" + "8968811499879834488085432887406099691357930743597400149880937810826749432741", + "11977891043796389746045421212159926311898450542234053989773610600930178192502", + "281501121614525983147332396469790211438622488475565642771817627682333786249", + "9100690296533618537163841894198029205677888291172371260364134732546626310463", + "17078348491431788399049547734294131771700242734225590181886718352299443291281", + "21450855024302726954615445057753830575555877588307435182621475316838615124820", + "10900431809146694428437984204538994994941533606094380937477886391625037447755", + "3337610403873013432150329465374313865426811710058525646376487899609930044935", + "16975838084504452463625049352327190703683489087250269524779720608562445888965", + "12222878022475487026765301282205034869637157752928126522553249839015554021118" ], "encPubKey": [ - "3246882523858798579653725632245677815572520121562528893682828338364433544239", - "251469813163058146760472586440492200141935016615685184229967914227285567741" + "18259975963345091655295771101429179848868646725131880720996723303604339718656", + "5206464926271134880990760175082419984245432672636643876804180999092396504284" ] } }, @@ -173,20 +173,20 @@ "type": "publishMessage", "data": { "message": [ - "6040209671941422224396602067545041920520358782195834435128413473696786837333", - "19960515712904479693190879460799401141735713693858466758411443985892378422179", - "18684049546709024405268090451084859257331206297993892767152697777168105193950", - "4417067055532741121958645526962600415558295671361599386718254482151320751800", - "8831014646401085985422075959553401353474401368058172621332926526032482358682", - "19217537575108723326676749657287652803032945360366531731763213424659467783655", - "18251504118463383519769062943112898564880497948309370456680815597871817867538", - "2086572403656215063854110231912436577966018392734032815223971612619051390233", - "4272366053435368552491549023761060025938452467762466263138690546603872915203", - "8120048915061515603211575426724595332593895770922805744882866281921989790750" + "384250227423424524743846099778205647880644114582802178551330269838114721778", + "6253382015299972856524497041806156052556864278773142985948064749712905559502", + "16205791792813047282393356053487039168153248190904924903955519781454779876283", + "8685554755079599033002452121689287945936800899267232527425584678107093392863", + "21857625177109487443646306527455375318708753234213479019215597976515860125183", + "1952848269938869966639100223194813465560788632850430518767374721509422657793", + "11741436154878781580853915187761588177600873659343581133673892605600902177112", + "5441761344436874846527893802746954285974761152499377876611490803004466213195", + "2158698878360782841061341132300015245999077402680697269938377882544062777354", + "14960023789636385476729202648247712537855087267413555807395516220422619308149" ], "encPubKey": [ - "19756256018645496875540731296733822049290414734956005295678189287448357913848", - "2707256377586192612467480538754151266138587489076506164860615112668134194308" + "2651644058252294902748096819293778357120124143797762100365512287127713627783", + "13171185775754670120173402036455084014002333400824314941541104745026848345420" ] } }, @@ -194,19 +194,19 @@ "type": "processMessage", "data": { "proof": { - "pi_a": "2129ce4afbd1ef82ebfc1ab787c4347898badf204d996aff3774e6ad9c3bc0421f68466d74479415df9140b7e8dd10a3069eb4e164c90b28eb3b7bab5297d718", - "pi_b": "10030e86baf67dfa8fe66d6da6f4a5ba6b71b2ec4756a13b27dd6cb5ef9c1c651735599e35f6074a6b24c484ba7cc551f6d20f31297d52dfba49eb6d80b00e7006b424e0213d6e832fdd704937bcece614195390f55fbc19669ebe474709dbac0af047834f35a11bcfabead0e400338a17aa64fac9fa2c52e2d1bc917ef733ae", - "pi_c": "1e604286ffb13ff0b0bec30eb81e9829f02208e649e672cb8da38b134e672a282220a5ce7be897ff5f31ca6dc8f76b4ba7b0a86d5bd52a9584e79421d73853a7" + "pi_a": "1505458b94654d8ace2efe171a53a1c4848fb5c4e53e843ca97c679744139b511858b468a2c64483e60f74cfe2062da135256244a0b272e911a3123092605db6", + "pi_b": "1f8d3d347cefe5c8b5b5ce56df3a404504581011a331124bf2d6aa6e04f0c2c42cff1d2e36c7479463a002a85909e6282fa5ba0f472cc5abba64531ed8842498124b466e80f26cdfcc95bd7067ee8ebe3ea56561774be27ddb8142aa8c446579058b3ab9a024202a1dbef60de357b8788704b18053814e8cace253bf94add4bb", + "pi_c": "120c4db956e7b325e16b5af69b25e2e51d402ae620a05eb9da849a1dd7d9723a07e04ddfa8abd975e83e5f6f4067c38e2c053601d1fae610463df01981c667b0" }, - "newStateCommitment": "15747144277495644891688004720427985491197111452878407902812834851808276585502" + "newStateCommitment": "7294752578784620390539752279591063208389533968884488588996398432974900514322" }, "inputs": [ "18446744086594453509", "6461578383827114485754732680455656069796650064243401842070626624889597928357", "0", - "526044335307134503491815026254278366672136736885761787302017270911568883596", - "6346528390895127279807599986474483438865420111586097124828966882255208009484", - "15747144277495644891688004720427985491197111452878407902812834851808276585502", + "7504625193227330538506566769358843157800673938191671210875712779760289416459", + "9227191193358443775699457971745319584512473689998474797530726497270008077098", + "7294752578784620390539752279591063208389533968884488588996398432974900514322", "16594648813117521549607651409199825676087230774332331178259600792935825001695", "1" ] @@ -215,15 +215,15 @@ "type": "processTally", "data": { "proof": { - "pi_a": "1d4d31970050c6dd47346215fa67a04a8b0b171539ba662d1e6643a4a116aef22289120a6384615ad650d8482223f6925f18311d82aecf58acfaff3a252f1c02", - "pi_b": "1dda84bf5bef508fde174efefe91723c9fa37c37b1a9719f4ccff9272125facd2f26e1cbb10fa46afdc770e12687630b9b56234e94967a61ba2d70ddc76bf37f21de8517756f16fe243ec4ca1b63ef999f5e59e25c76b6ce275197b970581f7227ccbcb1352195eda09fb8322fdbc313660459dd0be0c4c92982f875fd0c445a", - "pi_c": "2bbfa115c59f51affef995e5d3bdc2d317c576c5e1b60bfc092b807926f827c9078076b42e48c997dc9c308a26bcd01136b55584688d951e0ae77e1afaa0ba83" + "pi_a": "1279511748a3392610261c74ef288417dee879fa8760de4e747106f49de3d86721692a916d5d8775f2dbb09b3f8f137652e4c71381f45506d38bfc6ddeaaf43a", + "pi_b": "1ff4b65e4676468c9e75c1d3fa19e4aa7b2ff401a586d81e5966b54d624ce5451306edb424d489354257c0800eecbe093ad0cd67d2dae157daf93633f13fa5c723d7b3e58560218aa0df717425fd51b55e7013ce6c93674236ba2f7f842d7ee61b420296facdd3dd627e38575be3a7c6caa15d02461d6604de7743b8311a884b", + "pi_c": "1b5d9df41158e4780cf2ffd36bf5cc20668adb112d607a3d3631398c06ebda5511725b4c35175403f09d78d39dece2c92931f1ae4b7998d2c2734fdd95c43681" }, "newTallyCommitment": "5119554139732678588072159140519209785192441754076468540607385260141479782116" }, "inputs": [ "12884901888", - "15747144277495644891688004720427985491197111452878407902812834851808276585502", + "7294752578784620390539752279591063208389533968884488588996398432974900514322", "0", "5119554139732678588072159140519209785192441754076468540607385260141479782116" ] diff --git a/e2e/circuits/vkeys-amaci-2-1-1-5.json b/e2e/circuits/vkeys-amaci-2-1-1-5.json index 8fd3cfde..e725e8ca 100644 --- a/e2e/circuits/vkeys-amaci-2-1-1-5.json +++ b/e2e/circuits/vkeys-amaci-2-1-1-5.json @@ -13,7 +13,7 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "vk_delta_2": "0x19b3324e99e392444b416f376b6c1985756f2ce27ba8001611844b7709851c86076765c63f2a1ad176699fd24fab90f4a9fd10b7d934e73f168a892aeb8449b22048de2e2e86a887316a883b72b116c571aac32e2bb80fc875db2be20b4ce86e06d2c2711d7f387ccc6eacb5883ecfc78c729d37cf9970909b47b161f14b5763", "vk_ic0": "0x2109d20e2dfb65b2564cdd873f95f21a9215d9757c6ec62637b8d80373e1e9bb066ef0037b411d062439a5034b5c71bcdc2df0e3999fe5b7afd7cb88a32ceb30", "vk_ic1": "0x05199f9ffa6b1ec953808a3dd750ad9168ae7a1464ddcead6cf31d61530e22a215b34e716a4871c189f25cf43ebc656d3256812cb98179183df2a9da65da34b9" }, @@ -21,7 +21,7 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "vk_delta_2": "0x2747cb292b1263b86b325ae591e1e226049404334bb09165c6a7efac9744178b22508dbdabea8802179f8f2b7c9d064ab962fe834c16738721d03ad6db6836f9090497dc22da1e7959e91b42bba33f2b74c9f0c2a4a21055a7148b6716fb95e629bdc0b0b474b84c6e41687154ec37b95ccaed7d1a578fef1873dcc5e672d912", "vk_ic0": "0x0b20a7584a8679cc6cf8e8cffc41ce9ad79c2cd0086214c3cb1af12146916bb9185b916c9938601b30c6fc4e7f2e1f1a7a94cb81e1774cb1f67b54eb33477e82", "vk_ic1": "0x081919adecf04dd5e1c31a3e34f8907d2ca613df81f99b3aa56c5027cd6416c201ddf039c717b1d29ecc2381db6104506731132f624e60cc09675a100028de25" }, @@ -29,7 +29,7 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "vk_delta_2": "0x26f85af9fdc3df0a5ee4a7737e629eb22e1df46aea9c67767eb1c9fa16387a6b1e00017122d8106b5967c49f2e976cec95fdb80aeefd901e808e01c314963e771d7773994f156c2092b98f0e69c2987defa8c338b2e0f3dbe45d78112306782a07227a53bcb6ad9a60b84924da88f13275a9a4f29843b06bf89b2f072b6ab6a6", "vk_ic0": "0x141ed95aed8eac95334e6dbaa513736949402fd820920d8e2179d7be54593f60070ffd76988c62dbf2cf4a365da0fbecde7e7ccb39f1e0e0728a6941da3435cd", "vk_ic1": "0x2c1289b05f9093a1d4c7536093702b08d57654fae20ae871de2598565c43c8611d5bc6caad360c2b6f68480aa71efbcc506524104152bb73f79d9cb0f3d12180" }, @@ -37,8 +37,8 @@ "vk_alpha1": "0x2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926", "vk_beta_2": "0x0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8", "vk_gamma_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "vk_delta_2": "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "vk_delta_2": "0x07b9d5bf21365da183856ac35153c99e3778211de334e7dc31db2cd038cb3f84009c65360ff6b5581f7ef5ef43db9ce552ab6a085ed584e1c403a913d320f15c0fe6dbb6aba6461d43b49f4e3dca84aba1564e72bf6d9542e75fd6677834a9611b5c161cc38da933e6e4fb6ef58f5d4e04c19b6df7cab0c650b6c4d572ef5789", "vk_ic0": "0x29639aea06acd9b07e36d2456153d4e81581d65efb2fc93f0d54618398be1c471f49496bce6f344badecd9493d07faaaa2d09c7216734488f3ce2e2d0bd25be9", "vk_ic1": "0x20ccb32cbbbb10099ab8ef2bfd196ec22b3c07c8c7eba7076bb8d16be4aa69ad0b0ff4e2a298219ef216024cd65a8b26470a7daa2e8ce55af41038a74d5d589f" } -} +} \ No newline at end of file diff --git a/e2e/scripts/downloadZkeys.ts b/e2e/scripts/downloadZkeys.ts index 55479575..823e3c6f 100644 --- a/e2e/scripts/downloadZkeys.ts +++ b/e2e/scripts/downloadZkeys.ts @@ -24,7 +24,7 @@ const CIRCUITS_DIR = path.join(__dirname, '../circuits'); const CIRCUIT_CONFIGS: CircuitConfig[] = [ { name: 'AMACI', - url: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v5_zkeys.tar.gz', + url: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v6_zkeys.tar.gz', targetDir: path.join(CIRCUITS_DIR, 'amaci-2-1-1-5'), description: 'AMACI (state:2, int:1, vote:1, batch:5)', fileMapping: { @@ -105,7 +105,7 @@ async function downloadCircuitConfig(config: CircuitConfig): Promise { console.log(` 📁 Organizing files...`); - // Detect actual extracted dir (AMACI tar extracts to a versioned sub-directory, e.g. 2-1-1-5_v5/) + // Detect actual extracted dir (AMACI tar extracts to a versioned sub-directory, e.g. 2-1-1-5_v6/) const extractedPrefix = findExtractedZkeyDir(CIRCUITS_DIR); const pathPrefix = extractedPrefix ?? config.fileMapping.processMessagesWasm.slice(0, -1); if (extractedPrefix) { @@ -327,15 +327,15 @@ async function downloadAllZkeys(): Promise { if (fs.existsSync(addNewKeyWasm) && fs.existsSync(addNewKeyZkey)) { console.log(' ✅ AddNewKey files already exist, skipping download'); } else { - console.log(' 📥 Downloading addNewKey.wasm (v5)...'); + console.log(' 📥 Downloading addNewKey.wasm (v6)...'); await downloadFileWithRetry( - 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v5.wasm', + 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v6.wasm', addNewKeyWasm ); - console.log(' 📥 Downloading addNewKey.zkey (v5)...'); + console.log(' 📥 Downloading addNewKey.zkey (v6)...'); await downloadFileWithRetry( - 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v5.zkey', + 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v6.zkey', addNewKeyZkey ); diff --git a/packages/circuits/ts/generate-logs.ts b/packages/circuits/ts/generate-logs.ts index 473102ca..483b4263 100644 --- a/packages/circuits/ts/generate-logs.ts +++ b/packages/circuits/ts/generate-logs.ts @@ -11,9 +11,9 @@ import { OperatorClient, VoterClient, stringizing, adaptToUncompressed } from '@ // --local Use locally compiled artifacts (from circomkit's // `generate-zkeys`) for ALL 4 circuits (AddNewKey, // ProcessDeactivateMessages, ProcessMessages, TallyVotes) -// instead of downloading the remote v5 tarball. Required +// instead of downloading the remote v6 tarball. Required // whenever the circuits themselves changed (e.g. the -// maxVotesPerOption feature), since the remote v5 +// maxVotesPerOption feature), since the remote v6 // artifacts are built from an older circuit version and // are incompatible with the current circom/SDK code. // ============================================================ @@ -45,18 +45,18 @@ const LOCAL_TALLY_DIR = path.join(BUILD_DIR, 'TallyVotes_amaci_2-1-1'); const LOCAL_TALLY_WASM = path.join(LOCAL_TALLY_DIR, 'TallyVotes_amaci_2-1-1_js', 'TallyVotes_amaci_2-1-1.wasm'); const LOCAL_TALLY_ZKEY = path.join(LOCAL_TALLY_DIR, 'TallyVotes_amaci_2-1-1.0.zkey'); -// ---------- v5 remote zkey/wasm artifacts (amaci_2-1-1-5) ---------- -// The tar https://...amaci_2-1-1-5_v5_zkeys.tar.gz extracts to build/2-1-1-5/ +// ---------- v6 remote zkey/wasm artifacts (amaci_2-1-1-5) ---------- +// The tar https://...amaci_2-1-1-5_v6_zkeys.tar.gz extracts to build/2-1-1-5/ // with file names: deactivate.wasm/zkey, msg.wasm/zkey, tally.wasm/zkey -const ZKEYS_V5_BASE = path.join(BUILD_DIR, '2-1-1-5'); -const ZKEYS_V5_URLS = { - addNewKeyWasm: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v5.wasm', - addNewKeyZkey: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v5.zkey', - amaciZkeysTar: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v5_zkeys.tar.gz' +const ZKEYS_V6_BASE = path.join(BUILD_DIR, '2-1-1-5'); +const ZKEYS_V6_URLS = { + addNewKeyWasm: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v6.wasm', + addNewKeyZkey: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/add-new-key_2-1-1-5_v6.zkey', + amaciZkeysTar: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v6_zkeys.tar.gz' }; // Deactivate/ProcessMessages/TallyVotes circuit paths – resolved at runtime -// based on --local flag (remote v5 tar vs locally compiled circomkit artifacts) +// based on --local flag (remote v6 tar vs locally compiled circomkit artifacts) let DEACTIVATE_WASM: string; let DEACTIVATE_ZKEY: string; let MSG_WASM: string; @@ -135,13 +135,13 @@ function getRequiredRemoteArtifacts(): { name: string; p: string }[] { function ensureRemoteArtifacts(): void { const missing = getRequiredRemoteArtifacts().filter((a) => !fs.existsSync(a.p)); if (missing.length === 0) { - console.log('Remote v5 zkey/wasm present at', ZKEYS_V5_BASE); + console.log('Remote v6 zkey/wasm present at', ZKEYS_V6_BASE); return; } throw new Error( - `Missing remote v5 artifacts at ${ZKEYS_V5_BASE}: ${missing.map((a) => a.name).join(', ')}.\n` + - `Download and extract into ${path.dirname(ZKEYS_V5_BASE)}:\n` + - ` ${ZKEYS_V5_URLS.amaciZkeysTar}\n` + + `Missing remote v6 artifacts at ${ZKEYS_V6_BASE}: ${missing.map((a) => a.name).join(', ')}.\n` + + `Download and extract into ${path.dirname(ZKEYS_V6_BASE)}:\n` + + ` ${ZKEYS_V6_URLS.amaciZkeysTar}\n` + `(The tar should create a 2-1-1-5/ sub-directory automatically.)` ); } @@ -153,14 +153,14 @@ async function ensureArtifacts(): Promise { ADDKEY_WASM = LOCAL_ADDKEY_WASM; ADDKEY_ZKEY = LOCAL_ADDKEY_ZKEY; } else { - fs.mkdirSync(ZKEYS_V5_BASE, { recursive: true }); - const remoteAddkeyWasm = path.join(ZKEYS_V5_BASE, 'add-new-key_2-1-1-5_v5.wasm'); - const remoteAddkeyZkey = path.join(ZKEYS_V5_BASE, 'add-new-key_2-1-1-5_v5.zkey'); + fs.mkdirSync(ZKEYS_V6_BASE, { recursive: true }); + const remoteAddkeyWasm = path.join(ZKEYS_V6_BASE, 'add-new-key_2-1-1-5_v6.wasm'); + const remoteAddkeyZkey = path.join(ZKEYS_V6_BASE, 'add-new-key_2-1-1-5_v6.zkey'); if (!fs.existsSync(remoteAddkeyWasm) || !fs.existsSync(remoteAddkeyZkey)) { console.log('Downloading remote AddNewKey wasm/zkey...'); - await downloadFile(ZKEYS_V5_URLS.addNewKeyWasm, remoteAddkeyWasm); + await downloadFile(ZKEYS_V6_URLS.addNewKeyWasm, remoteAddkeyWasm); console.log('Downloaded add-new-key wasm'); - await downloadFile(ZKEYS_V5_URLS.addNewKeyZkey, remoteAddkeyZkey); + await downloadFile(ZKEYS_V6_URLS.addNewKeyZkey, remoteAddkeyZkey); console.log('Downloaded add-new-key zkey'); } ADDKEY_WASM = remoteAddkeyWasm; @@ -177,21 +177,21 @@ async function ensureArtifacts(): Promise { TALLY_WASM = LOCAL_TALLY_WASM; TALLY_ZKEY = LOCAL_TALLY_ZKEY; } else { - fs.mkdirSync(ZKEYS_V5_BASE, { recursive: true }); - DEACTIVATE_WASM = path.join(ZKEYS_V5_BASE, 'deactivate.wasm'); - DEACTIVATE_ZKEY = path.join(ZKEYS_V5_BASE, 'deactivate.zkey'); - MSG_WASM = path.join(ZKEYS_V5_BASE, 'msg.wasm'); - MSG_ZKEY = path.join(ZKEYS_V5_BASE, 'msg.zkey'); - TALLY_WASM = path.join(ZKEYS_V5_BASE, 'tally.wasm'); - TALLY_ZKEY = path.join(ZKEYS_V5_BASE, 'tally.zkey'); + fs.mkdirSync(ZKEYS_V6_BASE, { recursive: true }); + DEACTIVATE_WASM = path.join(ZKEYS_V6_BASE, 'deactivate.wasm'); + DEACTIVATE_ZKEY = path.join(ZKEYS_V6_BASE, 'deactivate.zkey'); + MSG_WASM = path.join(ZKEYS_V6_BASE, 'msg.wasm'); + MSG_ZKEY = path.join(ZKEYS_V6_BASE, 'msg.zkey'); + TALLY_WASM = path.join(ZKEYS_V6_BASE, 'tally.wasm'); + TALLY_ZKEY = path.join(ZKEYS_V6_BASE, 'tally.zkey'); // Download and extract remote amaci tar if deactivate/msg/tally are missing. // The tar extracts directly into BUILD_DIR creating the sub-directory 2-1-1-5/. const missingRemote = getRequiredRemoteArtifacts().filter((a) => !fs.existsSync(a.p)); if (missingRemote.length > 0) { - console.log('Downloading amaci v5 zkeys tar (deactivate/msg/tally)...'); - const tarPath = path.join(BUILD_DIR, 'amaci_2-1-1-5_v5_zkeys.tar.gz'); - await downloadFile(ZKEYS_V5_URLS.amaciZkeysTar, tarPath); + console.log('Downloading amaci v6 zkeys tar (deactivate/msg/tally)...'); + const tarPath = path.join(BUILD_DIR, 'amaci_2-1-1-5_v6_zkeys.tar.gz'); + await downloadFile(ZKEYS_V6_URLS.amaciZkeysTar, tarPath); console.log('Extracting amaci zkeys tar...'); execSync(`tar -xzf "${tarPath}" -C "${BUILD_DIR}"`, { stdio: 'inherit' }); try { fs.unlinkSync(tarPath); } catch { /* ignore */ } diff --git a/packages/cli/src/core/circuits.ts b/packages/cli/src/core/circuits.ts index 071f0f1f..ae22ea16 100644 --- a/packages/cli/src/core/circuits.ts +++ b/packages/cli/src/core/circuits.ts @@ -72,27 +72,27 @@ const CIRCUIT_9_4_3_125: AmaciCircuitEntry = { label: '9-4-3-125', production: true, source: 'vkeys_9_4_3_125() — maci/contracts/amaci/src/circuit_params.rs', - zkeyUrl: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_9-4-3-125_v5_zkeys.tar.gz', - zkeyTarSha256: '792352fddaaaab9ac16befe8dbabff1757598b55640f0476be1d2f8b935f9904', + zkeyUrl: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_9-4-3-125_v6_zkeys.tar.gz', + zkeyTarSha256: '0a0a983ca9cd15aaae1272b7e5f43392b93011856407d614b096398e4c833936', params: { stateTreeDepth: 9, intStateTreeDepth: 4, voteOptionTreeDepth: 3, messageBatchSize: 125 }, vkeys: { process: vkey( - '1ca282bdb2bf70aeae2a394515a6b090972b172f2baa302c9c4a5e2e62044085172b006b637672503a9ad454148c20024cc3412cd3af07fdc172cbeec61de5252e7f42a023bce7df1c2b9bb817d5c6345e03462f2231ef0b4057c487da87e4fa1df5a5ff810e7c9f18acf76a9ef37ed89169f54af3326f63e5c732886b57b0d0', - '0f4ca042d9df017c2277a5348138072354637d7a548ed2432a62b22bd6b0793c14d190e06d249c579f2f3cb9c0d8e5223798931ac8fc645efc96739d34e3a553', - '0231a17b99604840a6870d1c5ba31394ceb6683af703d083338c30bdb87b88851283ec802a494552bd00732fa61bfc619a4238a0ab6659e5c8fa91b2a5e5143b' + '059756653a474da0d3a99522bfba92428ff603c8254e3c5016c41fc532baadd42f456e58a452cc9ace1828ca8eafcda8685872703c35ef5d796e7e8bed5a4d00002d372c4d2bbccad47dbed288eaad7a6bce92f605f1082fa4442cf7555b6dff14eea0b33c1832a169e2e42dcb07749d88806193280fd009912ab35af8b2a2c2', + '2936807506628c01f5c320b0cfe38bcd7de3f1c9f78649cb2ee9fe835c523e602d716f08d8b98a688c9f106bb18060c66feaf31854327cf20dd3170a284f8258', + '0db49219818833defe6729fe69d23bbbd6c892b45b49792b798c13ff3ab72f3e1674142a207b3a01330a307e9613dc643b181a728bc4a041ad5a0ff37900c71c' ), tally: vkey( - '232a958bbc349f1fa27cf560c9efa7248aa95d954de64a3e170c2abe8265386529255f7c77a1a70b4237d6fa8763c64699c3d1eb62a54e60349cb32c850ef1b10044d8b3fc7298d54a097453c9a9b62442fa3851e2c1dc582c47b9d60e0a62392ca45e26a1793a485d1e8c81de124d2b1cf2afefa69459ef7d567076bc864dec', + '04ac819540c297e090f7798b260dedf91d7d07e0c28c935b1727e815fc0b690a04c5daab1db9d8cf8dd34f682d74f9cc692ad4c48402aad88c0071769e13b589013d75b834c55ff9b9f9d3dd8b2c736b836af659800f6b1b0b1602f3c6007add2d1fe9bebad5ca5847b53d2241fbf84c32ed836b3226136a213236fac682561b', '1840e9af4d2094c190adf2e40468515ee760858a2a41a26aa7916bc38bd7ba9f01ea24bf4adad4d679ddf5858dbcb4587b954a6062b264288f6e191c6d697759', '1ed068e3bbc130b6a420efe22b7f26b7372686108ff1935eea7508eb814d3e2e0ab2da2095988387330108bee8d58121be18e61bb594ba9b8982a290cfc2571b' ), deactivate: vkey( - '11e969c11af8421c1474c478725abee854af14412b35f69010f5c9913c9eb9401474968c8c1608ebdfb978f7e72380d046d1ac079a64bae0fef5052137ae829d07317efdfe94d826337c8225c7e78be3775f3dd61a60486fe32ca7587223c58323534bc421de3812160299521a2670b43351d8c6ef3a3204ab9394c05111f805', + '147cbe7e7451633254d01f220cf3521717258300cbe8eea7f9c5e4a5aa776a5d1fbe926fe9c14bf755a9c2ac403e2c94eaf9015dda20644279d115e9b8556904205164034510b8e0dbad7647a37b4d958247ac849463e291152460f3cc08cd3c2eeb4a102cd303af7fd64bf0d61319f658330f121373b9b5b983c2e680ba3d8d', '2341ef299bd50b06e3885f2c95e6e043ac4a9b30263fb5b212b9c5ee443ab28d17b0dd121483ee7a280fe8a82384e8bbd0e52c32be97148dfaecb953ee0b34fe', '04c3cdc1e32f4e6eae21adb419ed037dcd5daa9012bc9fe31e4ebedba31c101b00f8483d686d64d0eb7d1c3278b4409f4717dea169970f62505a52e3c08b6d4d' ), addNewKey: vkey( - '1c94083c2b90d4f41d7e83000647860bb278e98705f0c9553b790ba4556d88451b2e0741e3cba46801412cff620bb191ab358604fff432bf073a325c9f19a1860cb0286d5261f5e0214f11320d740fee711f78575a8f3b47bebecad7e16a301c0b0d80535eb8f30fd18c2627e9f08d1b1bf3f7210994465489722587bba1487f', + '0eb06f2f1b513f042895affc86f337c896aff1a9b0b158bbd3608ba3f27165862c47682ba5c8ebad4178c520f9d88e9bfa8cadf098baf2fe5509929131f909741d6888dd7e2462f4e7d0564ace9128facc836d221dff6c0b85181519ee039f2b04f70b9050f84fb9ca004fd086fab7ca49c9c07e32b841805147aa86930fdb9e', '0eb39e5aa053d6676afa84d88c23996669b18eda44eb6d97420176ff55c276290ae7df9c85d77b9aef313093fdeada3c53cd1b0cfd7ed04460a719cfff4e5925', '200467c396f31ec6b2f3324d5fa38a28e18ce24c1a92742486553e2375204fc82e4feff4af5e2c2ac4acd05af4a64d161edee15e1feef61d2f4977860643c94b' ), @@ -107,27 +107,27 @@ const CIRCUIT_2_1_1_5: AmaciCircuitEntry = { label: '2-1-1-5', production: false, source: 'vkeys_2_1_1_5() — maci/contracts/amaci/src/circuit_params.rs (test-only)', - zkeyUrl: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v5_zkeys.tar.gz', - zkeyTarSha256: '8cbe3e77c5126d203054869dc93f21db0409e0403aedd5f33b690eccccb9e494', + zkeyUrl: 'https://vota-zkey.s3.ap-southeast-1.amazonaws.com/amaci_2-1-1-5_v6_zkeys.tar.gz', + zkeyTarSha256: '67818182b14ef30cc8cdd978bffc04264f47b2db7e8cb3cc133a21a880d40f56', params: { stateTreeDepth: 2, intStateTreeDepth: 1, voteOptionTreeDepth: 1, messageBatchSize: 5 }, vkeys: { process: vkey( - '14fcf460ec67f39e7604ce59622a530797f70d5dce2cdbfcc6285acb11a091490a51cc6cc5aec73e4b1fcd45f152e8d18d9831efa2ca2d8aba5ec00a5258a86c2588c3053fe7907bd6e3b3b455283a441df9f5e9cc8b1aca6712d37004c28e4311915d144397caf4c4e74e150159574574d84d4a620cc22e1ee695b45f0c09fb', - '152b83fbeccaaf60ff7c47ebcefc9368d1d81271fc47d36e3032f589112849c900ce96219b641b39a390c8fe58b8ff805e21e55257e1437c26285d030fb52a70', - '0722c7bc6aaf03f86fc32096b9ad50fa14a99d113cd02d3a26df629703f7b9b61a19f057b25b77efefe232bb2cc87d9637bca988fc0325bd8c9e4b1febe5eca4' + '19b3324e99e392444b416f376b6c1985756f2ce27ba8001611844b7709851c86076765c63f2a1ad176699fd24fab90f4a9fd10b7d934e73f168a892aeb8449b22048de2e2e86a887316a883b72b116c571aac32e2bb80fc875db2be20b4ce86e06d2c2711d7f387ccc6eacb5883ecfc78c729d37cf9970909b47b161f14b5763', + '2109d20e2dfb65b2564cdd873f95f21a9215d9757c6ec62637b8d80373e1e9bb066ef0037b411d062439a5034b5c71bcdc2df0e3999fe5b7afd7cb88a32ceb30', + '05199f9ffa6b1ec953808a3dd750ad9168ae7a1464ddcead6cf31d61530e22a215b34e716a4871c189f25cf43ebc656d3256812cb98179183df2a9da65da34b9' ), tally: vkey( - '21770a545c0aaa828d45a00c7335a689ac65650edb60d582ae66928eb860ac8811ec3ee19549dc6bf84515db12f782b7c6848fe4d004d32a5d27bce19440c34a173c6f347154f90a6052e1ca1faf89d4940527f248597c340c5c6cdf436225342c0fa0a92e84c22bb553aa427aa53c0f5f3ba7f7d223f6eb89b7d7cba26eb070', + '2747cb292b1263b86b325ae591e1e226049404334bb09165c6a7efac9744178b22508dbdabea8802179f8f2b7c9d064ab962fe834c16738721d03ad6db6836f9090497dc22da1e7959e91b42bba33f2b74c9f0c2a4a21055a7148b6716fb95e629bdc0b0b474b84c6e41687154ec37b95ccaed7d1a578fef1873dcc5e672d912', '0b20a7584a8679cc6cf8e8cffc41ce9ad79c2cd0086214c3cb1af12146916bb9185b916c9938601b30c6fc4e7f2e1f1a7a94cb81e1774cb1f67b54eb33477e82', '081919adecf04dd5e1c31a3e34f8907d2ca613df81f99b3aa56c5027cd6416c201ddf039c717b1d29ecc2381db6104506731132f624e60cc09675a100028de25' ), deactivate: vkey( - '0b2b685a254c97378d11100e45db341efebcc5e3d026fe920fdf1cac04c5feb4135b02f250b191e658c55341d45184bde62cec70444c4f210fdb507d5622dc821fe7bc3e41c31a4e6b7288ca0d519b80b18e722712d24f8786155d683f0bff7101e736bd668785e26ceb252106aaa784c922e2509d37444c711da6b3d8d0c8ad', + '26f85af9fdc3df0a5ee4a7737e629eb22e1df46aea9c67767eb1c9fa16387a6b1e00017122d8106b5967c49f2e976cec95fdb80aeefd901e808e01c314963e771d7773994f156c2092b98f0e69c2987defa8c338b2e0f3dbe45d78112306782a07227a53bcb6ad9a60b84924da88f13275a9a4f29843b06bf89b2f072b6ab6a6', '141ed95aed8eac95334e6dbaa513736949402fd820920d8e2179d7be54593f60070ffd76988c62dbf2cf4a365da0fbecde7e7ccb39f1e0e0728a6941da3435cd', '2c1289b05f9093a1d4c7536093702b08d57654fae20ae871de2598565c43c8611d5bc6caad360c2b6f68480aa71efbcc506524104152bb73f79d9cb0f3d12180' ), addNewKey: vkey( - '2b135a96b33686a78339372bd40e3bef10aea0554c15a4770aeecdea0ce74b65265875823bf58d64d42fdf4ab9b8dba0a8b71dc2c1a140c68069d013a661c6a4150290c14390c9f212516d006b2b67012db77104bb20f3b980e924069a27c725119f442673a5ead331dfdfbbb1963ff41eca2f0a518e535f7b6b44cea1efd3df', + '07b9d5bf21365da183856ac35153c99e3778211de334e7dc31db2cd038cb3f84009c65360ff6b5581f7ef5ef43db9ce552ab6a085ed584e1c403a913d320f15c0fe6dbb6aba6461d43b49f4e3dca84aba1564e72bf6d9542e75fd6677834a9611b5c161cc38da933e6e4fb6ef58f5d4e04c19b6df7cab0c650b6c4d572ef5789', '29639aea06acd9b07e36d2456153d4e81581d65efb2fc93f0d54618398be1c471f49496bce6f344badecd9493d07faaaa2d09c7216734488f3ce2e2d0bd25be9', '20ccb32cbbbb10099ab8ef2bfd196ec22b3c07c8c7eba7076bb8d16be4aa69ad0b0ff4e2a298219ef216024cd65a8b26470a7daa2e8ce55af41038a74d5d589f' ), From 5cf6b86ab01d7557258807f901e3ee81eb479358 Mon Sep 17 00:00:00 2001 From: 99Kies <1290017556@qq.com> Date: Wed, 22 Jul 2026 21:56:58 +0800 Subject: [PATCH 6/6] fix: handle flat tar layout in downloadZkeys.ts extraction The v6 AMACI zkey tarball extracts flat into the circuits dir (no "2-1-1-5/" wrapper sub-directory like v5 did). findExtractedZkeyDir only scanned sub-directories for artifacts, so on a flat layout it fell back to a hardcoded prefix and failed with "Required file not found" in CI (this was never hit locally since the extraction was done manually there, bypassing the script's own logic). - findExtractedZkeyDir now also checks baseDir itself before recursing into sub-directories - Fix downstream logging/cleanup to handle an empty-array prefix (flat layout) without touching undefined paths or the whole circuits dir - Remove loose copied source files after organizing when the archive extracted flat, so they don't linger or get mistaken for a valid extraction on a future run --- e2e/scripts/downloadZkeys.ts | 60 ++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/e2e/scripts/downloadZkeys.ts b/e2e/scripts/downloadZkeys.ts index 823e3c6f..ed45ba5e 100644 --- a/e2e/scripts/downloadZkeys.ts +++ b/e2e/scripts/downloadZkeys.ts @@ -48,16 +48,20 @@ const SKIP_DIRS = new Set(['amaci-2-1-1-5', 'amaci-4-2-2-25', 'maci-2-1-1-5', 'm */ function findExtractedZkeyDir(baseDir: string, segments: string[] = []): string[] | null { if (!fs.existsSync(baseDir)) return null; + + // v6+ tarballs may extract flat (artifacts directly inside baseDir, no wrapper + // sub-directory) instead of nesting under e.g. "2-1-1-5/". Check baseDir itself first. + const hasArtifactsHere = + fs.existsSync(path.join(baseDir, 'msg.wasm')) || + fs.existsSync(path.join(baseDir, 'msg.zkey')) || + fs.existsSync(path.join(baseDir, 'processMessages.wasm')) || + fs.existsSync(path.join(baseDir, 'processMessages.zkey')); + if (hasArtifactsHere) return segments; + const entries = fs.readdirSync(baseDir, { withFileTypes: true }); for (const e of entries) { if (!e.isDirectory() || SKIP_DIRS.has(e.name)) continue; const dirPath = path.join(baseDir, e.name); - const hasArtifacts = - fs.existsSync(path.join(dirPath, 'msg.wasm')) || - fs.existsSync(path.join(dirPath, 'msg.zkey')) || - fs.existsSync(path.join(dirPath, 'processMessages.wasm')) || - fs.existsSync(path.join(dirPath, 'processMessages.zkey')); - if (hasArtifacts) return [...segments, e.name]; const found = findExtractedZkeyDir(dirPath, [...segments, e.name]); if (found) return found; } @@ -105,11 +109,14 @@ async function downloadCircuitConfig(config: CircuitConfig): Promise { console.log(` 📁 Organizing files...`); - // Detect actual extracted dir (AMACI tar extracts to a versioned sub-directory, e.g. 2-1-1-5_v6/) + // Detect actual extracted dir. AMACI tar may extract to a versioned sub-directory + // (e.g. 2-1-1-5_v5/), or flat directly into CIRCUITS_DIR with no wrapper folder (v6+). const extractedPrefix = findExtractedZkeyDir(CIRCUITS_DIR); const pathPrefix = extractedPrefix ?? config.fileMapping.processMessagesWasm.slice(0, -1); - if (extractedPrefix) { + if (extractedPrefix && extractedPrefix.length > 0) { console.log(` 📂 Found files in: ${extractedPrefix.join('/')}`); + } else if (extractedPrefix) { + console.log(` 📂 Found files directly in circuits directory (flat archive layout)`); } // v4 tarball uses processMessages.wasm / tallyVotes.wasm; v3 uses msg.wasm / tally.wasm @@ -166,8 +173,15 @@ async function downloadCircuitConfig(config: CircuitConfig): Promise { fs.unlinkSync(tarFilePath); } - // Remove extracted dirs (zkeys, zkey, r1cs, or detected top-level) - const extractedDirs = ['zkeys', 'zkey', 'r1cs', ...(extractedPrefix ? [extractedPrefix[0]] : [])]; + // Remove extracted dirs (zkeys, zkey, r1cs, or the detected wrapper top-level dir). + // Only relevant when the tar extracted into a nested sub-directory; a flat archive + // (extractedPrefix.length === 0) has no wrapper dir to remove here. + const extractedDirs = [ + 'zkeys', + 'zkey', + 'r1cs', + ...(extractedPrefix && extractedPrefix.length > 0 ? [extractedPrefix[0]] : []) + ]; const toRemove = new Set(extractedDirs); for (const dir of toRemove) { const dirPath = path.join(CIRCUITS_DIR, dir); @@ -176,6 +190,32 @@ async function downloadCircuitConfig(config: CircuitConfig): Promise { } } + // If the tar extracted flat into CIRCUITS_DIR itself (no wrapper sub-directory), + // remove the loose source files we just copied so they don't linger as clutter or + // get mistaken for a valid extraction (with stale content) on a future run. + if (extractedPrefix && extractedPrefix.length === 0) { + const looseFiles = [ + 'msg.wasm', + 'msg.zkey', + 'tally.wasm', + 'tally.zkey', + 'processMessages.wasm', + 'processMessages.zkey', + 'tallyVotes.wasm', + 'tallyVotes.zkey', + 'deactivate.wasm', + 'deactivate.zkey', + 'addNewKey.wasm', + 'addNewKey.zkey' + ]; + for (const name of looseFiles) { + const filePath = path.join(CIRCUITS_DIR, name); + if (fs.existsSync(filePath)) { + fs.unlinkSync(filePath); + } + } + } + // Verify extracted files console.log(` 📋 Verifying files:`); for (const file of requiredFiles) {