Skip to content

Commit

Permalink
Merge pull request #70 from Yoii-Inc/feat/werewolf_cli_judging_winner
Browse files Browse the repository at this point in the history
Feat/werewolf cli judging winner
  • Loading branch information
taskooh authored Nov 11, 2024
2 parents e85eb3c + 35e02c4 commit be1c470
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 5 deletions.
129 changes: 128 additions & 1 deletion examples/werewolf_cli/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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;
Expand Down Expand Up @@ -229,12 +234,16 @@ impl Game {
};
}

pub fn check_victory_condition(&self) -> Option<String> {
pub fn check_victory_condition(&self, is_prove: bool) -> Option<String> {
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 {
Expand All @@ -244,6 +253,124 @@ impl Game {
}
}

fn prove_and_verify_victory(&self) {
// setup

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::<Vec<usize>>();

let rng = &mut test_rng();

let am_werewolf_vec = alive_indices
.iter()
.map(|_| InputWithCommit::default())
.collect::<Vec<_>>();

let mpc_am_werewolf_vec = alive_indices
.iter()
.map(|&i| {
let mut a: InputWithCommit<MFr> = InputWithCommit::default();
a.allocation = i;
a.input = MFr::from(self.state.players[i].is_werewolf());
a
})
.collect::<Vec<_>>();

let pedersen_param = self.state.pedersen_param.clone();
let mpc_pedersen_param =
<MFr as LocalOrMPC<MFr>>::PedersenParam::from_local(&pedersen_param);

let common_randomness = <Fr as LocalOrMPC<Fr>>::PedersenRandomness::pub_rand(rng);
let mpc_common_randomness =
<MFr as LocalOrMPC<MFr>>::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::<Vec<_>>();

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 + 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
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 =
<MFr as LocalOrMPC<MFr>>::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::<Vec<_>>(),
player_commitment: player_commitment
.iter()
.map(|x| <MFr as LocalOrMPC<MFr>>::PedersenCommitment::from_public(*x))
.collect::<Vec<_>>(),
};

let mut inputs = player_commitment
.iter()
.flat_map(|c| vec![c.x, c.y])
.collect::<Vec<_>>();

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<String> {
let mut events = Vec::new();

Expand Down
14 changes: 11 additions & 3 deletions examples/werewolf_cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,29 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

let mut game = Game::new(register_players(), game_rule);

game.role_assignment(false);
game.role_assignment(true);

println!("{:?}", game.state.players);

generate_random_commitment(&mut thread_rng(), &game.state.pedersen_param);

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();
Expand Down
1 change: 1 addition & 0 deletions mpc-algebra/src/wire/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ impl<F: PrimeField + SquareRootField, S: FieldShare<F>> LessThan for MpcField<F,
!lsb_x
}

// TODO: Fix: This function should be returns false when the two values are equal.
fn is_smaller_than(&self, other: &Self) -> Self::Output {
let timer = start_timer!(|| "LessThan");
// [z]=[other−self<p/2],[x]=[self<p/2],[y]=[other>p/2]
Expand Down
2 changes: 1 addition & 1 deletion src/marlin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn setup_and_index<C: ConstraintSynthesizer<Fr>>(
IndexVerifierKey<Fr, LocalMarlinKZG10>,
) {
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)
Expand Down

0 comments on commit be1c470

Please sign in to comment.