Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/werewolf cli judging winner #70

Merged
merged 3 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading