Skip to content

Commit fcbd12e

Browse files
author
Esau
committed
init
1 parent a37f1e5 commit fcbd12e

File tree

3 files changed

+374
-43
lines changed

3 files changed

+374
-43
lines changed

src/game_round_note.nr

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use aztec::{macros::notes::note, protocol_types::{traits::Packable, address::AztecAddress}};
2+
3+
#[derive(Eq, Packable)]
4+
#[note]
5+
pub struct GameRoundNote {
6+
pub track1: u8,
7+
pub track2: u8,
8+
pub track3: u8,
9+
pub track4: u8,
10+
pub track5: u8,
11+
pub round: u8,
12+
pub owner: AztecAddress,
13+
}
14+
15+
impl GameRoundNote {
16+
pub fn new(track1: u8, track2: u8, track3: u8, track4: u8, track5: u8, round: u8, owner: AztecAddress) -> Self {
17+
Self {
18+
track1,
19+
track2,
20+
track3,
21+
track4,
22+
track5,
23+
round,
24+
owner,
25+
}
26+
}
27+
28+
pub fn get(self) -> Self {
29+
Self {
30+
track1: self.track1,
31+
track2: self.track2,
32+
track3: self.track3,
33+
track4: self.track4,
34+
track5: self.track5,
35+
round: self.round,
36+
owner: self.owner,
37+
}
38+
}
39+
}

src/main.nr

Lines changed: 107 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,137 @@
1-
mod test;
2-
use dep::aztec::macros::aztec;
1+
// mod test;
2+
mod game_round_note;
3+
mod race;
34

4-
/**
5-
* WARNING: this is no-longer considered a good example of an Aztec contract,
6-
* because it touches low-level functions and concepts that oughtn't be
7-
* seen by a typical user.
8-
* The syntax and user-experience of Aztec contracts has since improved, so you
9-
* should seek alternative examples, please.
10-
*/
5+
use dep::aztec::macros::aztec;
116

127
#[aztec]
13-
pub contract PrivateVoting {
8+
pub contract PodRacing {
149
use dep::aztec::{
15-
keys::getters::get_public_keys,
10+
note::note_getter_options::NoteGetterOptions,
11+
messages::message_delivery::MessageDelivery,
1612
macros::{functions::{external, initializer, internal}, storage::storage},
1713
};
18-
use dep::aztec::protocol_types::{
19-
address::AztecAddress,
20-
hash::poseidon2_hash,
21-
traits::{Hash, ToField},
22-
};
23-
use dep::aztec::state_vars::{Map, PublicImmutable, PublicMutable};
14+
use dep::aztec::protocol_types::address::AztecAddress;
15+
use dep::aztec::state_vars::{Map, PublicMutable, PrivateSet};
16+
17+
use crate::{game_round_note::GameRoundNote, race::Race};
18+
19+
global TOTAL_ROUNDS: u8 = 3;
20+
global GAME_LENGTH: u32 = 300;
2421

2522
#[storage]
2623
struct Storage<Context> {
27-
admin: PublicMutable<AztecAddress, Context>, // admin can end vote
28-
tally: Map<Field, PublicMutable<Field, Context>, Context>, // we will store candidate as key and number of votes as value
29-
vote_ended: PublicMutable<bool, Context>, // vote_ended is boolean
30-
active_at_block: PublicImmutable<u32, Context>, // when people can start voting
24+
admin: PublicMutable<AztecAddress, Context>,
25+
races: Map<Field, PublicMutable<Race, Context>, Context>,
26+
progress: Map<Field, PrivateSet<GameRoundNote, Context>, Context>,
27+
win_history: Map<AztecAddress, PublicMutable<u64, Context>, Context>,
3128
}
3229

3330
#[external("public")]
3431
#[initializer]
35-
// annotation to mark function as a constructor
3632
fn constructor(admin: AztecAddress) {
3733
storage.admin.write(admin);
38-
storage.vote_ended.write(false);
39-
storage.active_at_block.initialize(context.block_number());
34+
}
35+
36+
#[external("public")]
37+
fn create_game(game_id: Field) {
38+
assert(storage.races.at(game_id).read().player1.eq(AztecAddress::zero()));
39+
40+
let game = Race::new(context.msg_sender().unwrap(), TOTAL_ROUNDS, context.block_number() + GAME_LENGTH);
41+
storage.races.at(game_id).write(game);
42+
}
43+
44+
#[external("public")]
45+
fn join_game(game_id: Field) {
46+
let maybe_existing_game = storage.races.at(game_id).read();
47+
48+
let joined_game = maybe_existing_game.join(context.msg_sender().unwrap());
49+
storage.races.at(game_id).write(joined_game);
4050
}
4151

4252
#[external("private")]
43-
// annotation to mark function as private and expose private context
44-
fn cast_vote(candidate: Field) {
45-
let msg_sender_nullifier_public_key_message_hash =
46-
get_public_keys(context.msg_sender().unwrap()).npk_m.hash();
47-
48-
let secret = context.request_nsk_app(msg_sender_nullifier_public_key_message_hash); // get secret key of caller of function
49-
let nullifier = poseidon2_hash([context.msg_sender().unwrap().to_field(), secret]); // derive nullifier from sender and secret
50-
context.push_nullifier(nullifier);
51-
PrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(
53+
fn play_round(game_id: Field, round: u8, track1: u8, track2: u8, track3: u8, track4: u8, track5: u8) {
54+
assert(track1 + track2 + track3 + track4 + track5 < 10);
55+
56+
storage.progress.at(game_id).insert(GameRoundNote::new(
57+
track1,
58+
track2,
59+
track3,
60+
track4,
61+
track5,
62+
round,
63+
context.msg_sender().unwrap(),
64+
)).emit(context.msg_sender().unwrap(), MessageDelivery.CONSTRAINED_ONCHAIN);
65+
66+
PodRacing::at(context.this_address()).validate_and_play_round(context.msg_sender().unwrap(), game_id, round).enqueue(
5267
&mut context,
5368
);
5469
}
5570

5671
#[external("public")]
5772
#[internal]
58-
fn add_to_tally_public(candidate: Field) {
59-
assert(storage.vote_ended.read() == false, "Vote has ended"); // assert that vote has not ended
60-
let new_tally = storage.tally.at(candidate).read() + 1;
61-
storage.tally.at(candidate).write(new_tally);
73+
fn validate_and_play_round(player: AztecAddress, game_id: Field, round: u8) {
74+
let game_in_progress = storage.races.at(game_id).read();
75+
storage.races.at(game_id).write(game_in_progress.increment_player_round(player, round));
76+
}
77+
78+
#[external("private")]
79+
fn finish_game(player: AztecAddress, game_id: Field, round: u8) {
80+
let totals = storage.progress.at(game_id).get_notes(NoteGetterOptions::new());
81+
82+
let mut total_track1: u64= 0;
83+
let mut total_track2: u64= 0;
84+
let mut total_track3: u64= 0;
85+
let mut total_track4: u64= 0;
86+
let mut total_track5: u64= 0;
87+
88+
for i in 0..TOTAL_ROUNDS {
89+
total_track1 += totals.get(i as u32).note.track1 as u64;
90+
total_track2 += totals.get(i as u32).note.track2 as u64;
91+
total_track3 += totals.get(i as u32).note.track3 as u64;
92+
total_track4 += totals.get(i as u32).note.track4 as u64;
93+
total_track5 += totals.get(i as u32).note.track5 as u64;
94+
}
95+
96+
PodRacing::at(context.this_address()).validate_finish_game_and_reveal(
97+
context.msg_sender().unwrap(),
98+
game_id,
99+
total_track1,
100+
total_track2,
101+
total_track3,
102+
total_track4,
103+
total_track5,
104+
).enqueue(
105+
&mut context,
106+
);
62107
}
63108

64109
#[external("public")]
65-
fn end_vote() {
66-
assert(storage.admin.read().eq(context.msg_sender().unwrap()), "Only admin can end votes"); // assert that caller is admin
67-
storage.vote_ended.write(true);
110+
#[internal]
111+
fn validate_finish_game_and_reveal(
112+
player: AztecAddress,
113+
game_id: Field,
114+
total_track1: u64,
115+
total_track2: u64,
116+
total_track3: u64,
117+
total_track4: u64,
118+
total_track5: u64
119+
) {
120+
let game_in_progress = storage.races.at(game_id).read();
121+
122+
storage.races.at(game_id).write(game_in_progress.set_player_scores(player, total_track1, total_track2, total_track3, total_track4, total_track5));
68123
}
69-
#[external("utility")]
70-
unconstrained fn get_vote(candidate: Field) -> Field {
71-
storage.tally.at(candidate).read()
124+
125+
#[external("public")]
126+
fn finalize_game(
127+
game_id: Field
128+
) {
129+
let game_in_progress = storage.races.at(game_id).read();
130+
131+
let winner = game_in_progress.calculate_winner(context.block_number());
132+
133+
let previous_wins = storage.win_history.at(winner).read();
134+
135+
storage.win_history.at(winner).write(previous_wins + 1);
72136
}
73137
}

0 commit comments

Comments
 (0)