From adb73e7eed577e531ae1860b0a5f52fb2ac97c1a Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Tue, 5 Nov 2024 16:42:08 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20Add:=20Implement=20prove/verify?= =?UTF-8?q?=20in=20judging=20winner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/werewolf_cli/game.rs | 117 +++++++++++++++++++++++++++++++++- examples/werewolf_cli/main.rs | 14 +++- 2 files changed, 127 insertions(+), 4 deletions(-) diff --git a/examples/werewolf_cli/game.rs b/examples/werewolf_cli/game.rs index 8ed8454..dc2205f 100644 --- a/examples/werewolf_cli/game.rs +++ b/examples/werewolf_cli/game.rs @@ -6,9 +6,12 @@ use ark_ff::UniformRand; use ark_marlin::IndexProverKey; use ark_std::test_rng; use ark_std::One; +use ark_std::PubUniformRand; use mpc_algebra::commitment::CommitmentScheme; use mpc_algebra::BooleanWire; +use mpc_algebra::EqualityZero; use mpc_algebra::FromLocal; +use mpc_algebra::LessThan; use mpc_algebra::MpcBooleanField; use mpc_algebra::Reveal; use mpc_net::{MpcMultiNet as Net, MpcNet}; @@ -18,6 +21,8 @@ use rand::Rng; use zk_mpc::circuits::AnonymousVotingCircuit; use zk_mpc::circuits::LocalOrMPC; use zk_mpc::circuits::RoleAssignmentCircuit; +use zk_mpc::circuits::WinningJudgeCircuit; +use zk_mpc::input::InputWithCommit; use zk_mpc::marlin::prove_and_verify; use zk_mpc::marlin::setup_and_index; use zk_mpc::marlin::LocalMarlin; @@ -229,12 +234,16 @@ impl Game { }; } - pub fn check_victory_condition(&self) -> Option { + pub fn check_victory_condition(&self, is_prove: bool) -> Option { let alive_players: Vec<&Player> = self.state.players.iter().filter(|p| p.is_alive).collect(); let werewolf_count = alive_players.iter().filter(|p| p.is_werewolf()).count(); let villager_count = alive_players.len() - werewolf_count; + if is_prove { + self.prove_and_verify_victory(); + } + if werewolf_count == 0 { Some("村人".to_string()) } else if werewolf_count >= villager_count { @@ -244,6 +253,112 @@ impl Game { } } + fn prove_and_verify_victory(&self) { + // setup + + let player_num = self.state.players.len(); + let num_alive = Fr::from(self.state.players.iter().filter(|p| p.is_alive).count() as i32); + + let rng = &mut test_rng(); + + let am_werewolf_vec = (0..player_num) + .map(|_| InputWithCommit::default()) + .collect::>(); + + let am_werewolf_val = (0..player_num) + .map(|i| self.state.players[i].is_werewolf()) + .collect::>(); + + let mpc_am_werewolf_vec = (0..player_num) + .map(|i| { + let mut a: InputWithCommit = InputWithCommit::default(); + a.allocation = i; + a.input = MFr::from(am_werewolf_val[i]); + a + }) + .collect::>(); + + let pedersen_param = self.state.pedersen_param.clone(); + let mpc_pedersen_param = + >::PedersenParam::from_local(&pedersen_param); + + let common_randomness = >::PedersenRandomness::pub_rand(rng); + let mpc_common_randomness = + >::PedersenRandomness::from_public(common_randomness); + + let mpc_am_werewolf_vec = mpc_am_werewolf_vec + .iter() + .map(|x| x.generate_input(&mpc_pedersen_param, &mpc_common_randomness)) + .collect::>(); + + let player_randomness = load_random_value().unwrap(); + let player_commitment = load_random_commitment().unwrap(); + + // calc + + let num_werewolf = mpc_am_werewolf_vec + .iter() + .fold(MFr::default(), |acc, x| acc + x.input); + let num_citizen = MFr::from_public(num_alive) - num_werewolf; + let exists_werewolf = num_werewolf.is_zero_shared(); + + let game_state = exists_werewolf.field() * MFr::from(2_u32) + + (!exists_werewolf).field() + * (num_werewolf.is_smaller_than(&num_citizen).field() * MFr::from(3_u32) + + (MFr::one() - (num_werewolf.is_smaller_than(&num_citizen)).field()) + * MFr::from(1_u32)); + + // prove + let local_judgment_circuit = WinningJudgeCircuit { + num_alive, + pedersen_param: pedersen_param.clone(), + am_werewolf: am_werewolf_vec.clone(), + game_state: Fr::default(), + + player_randomness: player_randomness.clone(), + player_commitment: player_commitment.clone(), + }; + + let (mpc_index_pk, index_vk) = setup_and_index(local_judgment_circuit); + + let mpc_pedersen_param = + >::PedersenParam::from_local(&pedersen_param); + + let mpc_judgment_circuit = WinningJudgeCircuit { + num_alive: MFr::from_public(num_alive), + pedersen_param: mpc_pedersen_param, + am_werewolf: mpc_am_werewolf_vec.clone(), + game_state, + player_randomness: player_randomness + .iter() + .map(|x| MFr::from_public(*x)) + .collect::>(), + player_commitment: player_commitment + .iter() + .map(|x| >::PedersenCommitment::from_public(*x)) + .collect::>(), + }; + + let mut inputs = player_commitment + .iter() + .flat_map(|c| vec![c.x, c.y]) + .collect::>(); + + inputs.extend_from_slice(&[num_alive, game_state.reveal()]); + + for iwc in mpc_am_werewolf_vec.iter() { + inputs.push(iwc.commitment.reveal().x); + inputs.push(iwc.commitment.reveal().y); + } + + assert!(prove_and_verify( + &mpc_index_pk, + &index_vk, + mpc_judgment_circuit.clone(), + inputs + )); + } + pub fn werewolf_attack(&mut self, target_id: MFr) -> Vec { let mut events = Vec::new(); diff --git a/examples/werewolf_cli/main.rs b/examples/werewolf_cli/main.rs index f1b78f8..4a22736 100644 --- a/examples/werewolf_cli/main.rs +++ b/examples/werewolf_cli/main.rs @@ -53,7 +53,7 @@ fn main() -> Result<(), Box> { let mut game = Game::new(register_players(), game_rule); - game.role_assignment(false); + game.role_assignment(true); println!("{:?}", game.state.players); @@ -61,13 +61,21 @@ fn main() -> Result<(), Box> { loop { night_phase(&mut game); + if game.state.day > 1 { + if let Some(winner) = game.check_victory_condition(true) { + println!("Game is over! {} wins!", winner); + break; + } + } morning_phase(&mut game); discussion_phase(&game); voting_phase(&mut game); - if let Some(winner) = game.check_victory_condition() { - println!("ゲーム終了!{}の勝利です!", winner); + if let Some(winner) = game.check_victory_condition(true) { + println!("Game is over! {} wins!", winner); break; + } else { + println!("Despite the execution, a terrifying night is coming."); } game.next_phase(); From a4139556d1bc7c998812a31e7c782ef3afadd10a Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Tue, 5 Nov 2024 16:43:12 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=A9=B9=20Update:=20Marlin=20srs=20par?= =?UTF-8?q?ameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/marlin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/marlin.rs b/src/marlin.rs index eb26f90..eae2671 100644 --- a/src/marlin.rs +++ b/src/marlin.rs @@ -39,7 +39,7 @@ pub fn setup_and_index>( IndexVerifierKey, ) { let rng = &mut test_rng(); - let srs = LocalMarlin::universal_setup(30000, 500, 1000, rng).unwrap(); + let srs = LocalMarlin::universal_setup(60000, 500, 1000, rng).unwrap(); let (index_pk, index_vk) = LocalMarlin::index(&srs, circuit).unwrap(); let mpc_index_pk = IndexProverKey::from_public(index_pk); (mpc_index_pk, index_vk) From 35e02c428086ee04357aaef7cc22a13f0768caa7 Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Sat, 9 Nov 2024 00:21:30 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20Fix:=20remove=20the=20judgme?= =?UTF-8?q?nt=20bug=20when=20some=20players=20are=20dead.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/werewolf_cli/game.rs | 34 +++++++++++++++++++++++----------- mpc-algebra/src/wire/field.rs | 1 + 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/examples/werewolf_cli/game.rs b/examples/werewolf_cli/game.rs index dc2205f..6023ca6 100644 --- a/examples/werewolf_cli/game.rs +++ b/examples/werewolf_cli/game.rs @@ -256,24 +256,30 @@ impl Game { fn prove_and_verify_victory(&self) { // setup - let player_num = self.state.players.len(); let num_alive = Fr::from(self.state.players.iter().filter(|p| p.is_alive).count() as i32); + let alive_indices = self + .state + .players + .iter() + .enumerate() + .filter(|(_, p)| p.is_alive) + .map(|(i, _)| i) + .collect::>(); + let rng = &mut test_rng(); - let am_werewolf_vec = (0..player_num) + let am_werewolf_vec = alive_indices + .iter() .map(|_| InputWithCommit::default()) .collect::>(); - let am_werewolf_val = (0..player_num) - .map(|i| self.state.players[i].is_werewolf()) - .collect::>(); - - let mpc_am_werewolf_vec = (0..player_num) - .map(|i| { + let mpc_am_werewolf_vec = alive_indices + .iter() + .map(|&i| { let mut a: InputWithCommit = InputWithCommit::default(); a.allocation = i; - a.input = MFr::from(am_werewolf_val[i]); + a.input = MFr::from(self.state.players[i].is_werewolf()); a }) .collect::>(); @@ -304,8 +310,14 @@ impl Game { let game_state = exists_werewolf.field() * MFr::from(2_u32) + (!exists_werewolf).field() - * (num_werewolf.is_smaller_than(&num_citizen).field() * MFr::from(3_u32) - + (MFr::one() - (num_werewolf.is_smaller_than(&num_citizen)).field()) + * ((num_werewolf + MFr::one()) + .is_smaller_than(&num_citizen) + .field() + * MFr::from(3_u32) + + (MFr::one() + - ((num_werewolf + MFr::one()) + .is_smaller_than(&num_citizen) + .field())) * MFr::from(1_u32)); // prove diff --git a/mpc-algebra/src/wire/field.rs b/mpc-algebra/src/wire/field.rs index 235623c..c626b54 100644 --- a/mpc-algebra/src/wire/field.rs +++ b/mpc-algebra/src/wire/field.rs @@ -261,6 +261,7 @@ impl> LessThan for MpcField Self::Output { let timer = start_timer!(|| "LessThan"); // [z]=[other−self

p/2]