Skip to content
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
2 changes: 1 addition & 1 deletion .github/scripts/update_contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ echo "version tag: $version_tag"
nargo_file_path="$copy_to_file_path/Nargo.toml"

repo_url="https://github.com/AztecProtocol/aztec-packages.git"
contracts_path="yarn-project/noir-contracts/src/contracts"
contracts_path="yarn-project/noir-contracts/contracts"

# Check if the file exists
if [ ! -f "$nargo_file_path" ]; then
Expand Down
9 changes: 6 additions & 3 deletions Nargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@

[package]
name = "easy_private_voting_contract"
type = "contract"
authors = [""]
authors = [
"",
]
compiler_version = ">=0.18.0"

[dependencies]
aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="aztec-packages-v0.16.9", directory="yarn-project/aztec-nr/aztec" }
protocol_types = { git="https://github.com/AztecProtocol/aztec-packages/", tag="aztec-packages-v0.16.9", directory="yarn-project/noir-protocol-circuits/src/crates/types"}
aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "aztec-packages-v0.17.0", directory = "yarn-project/aztec-nr/aztec" }
protocol_types = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "aztec-packages-v0.17.0", directory = "yarn-project/noir-protocol-circuits/src/crates/types" }
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ yarn install
## Compile

```bash
aztec-cli compile . --typescript ./src/artifacts
aztec-nargo compile
```

or
Expand All @@ -40,16 +40,24 @@ or
yarn compile
```

## Codegen

Generate the contract artifact json and typescript interface

```bash
yarn codegen
```

## Deploy

Add `ADMIN` to your environment.

```bash
ADMIN=0x1d30d4de97657983408587c7a91ba6587774b30f0e70224a0658f0357092f495
ADMIN="0x1d30d4de97657983408587c7a91ba6587774b30f0e70224a0658f0357092f495"
```

```bash
aztec-cli deploy ./target/EasyPrivateVoting.json --args $ADMIN
aztec-cli deploy src/artifacts/EasyPrivateVoting.json --args $ADMIN
```

## Test
Expand All @@ -60,6 +68,12 @@ yarn test

## Error resolution

### Update Nodejs and Noir dependencies

```bash
aztec-cli update
```

### Update Contract

Get the contract code from the monorepo. The script will look at the versions defined in `./Nargo.toml` and fetch that version of the code from the monorepo.
Expand All @@ -68,8 +82,6 @@ Get the contract code from the monorepo. The script will look at the versions de
yarn update
```

You may need to manually update the aztec packages in `./package.json` to the latest version.

You may need to update permissions with:

```bash
Expand Down
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@
"type": "module",
"scripts": {
"clean": "rm -rf ./src/artifacts ./target",
"compile": "aztec-cli compile --typescript ./src/artifacts .",
"codegen": "${AZTEC_CLI:-aztec-cli} codegen target --outdir src/artifacts --ts",
"compile": "${AZTEC_NARGO:-aztec-nargo} compile",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --config jest.integration.config.json",
"update": "./.github/scripts/update_contract.sh $(grep -oP 'tag=\"\\K[^\"]+' \"Nargo.toml\" | head -1)"
"update": "./.github/scripts/update_contract.sh $(grep -oP 'tag\\s*=\\s*\"\\K[^\"]+' \"Nargo.toml\" | head -1)"
},
"dependencies": {
"@aztec/aztec.js": "^0.16.9"
"@aztec/aztec.js": "0.17.0"
},
"devDependencies": {
"@aztec/noir-contracts": "^0.16.9",
"@aztec/noir-contracts": "0.17.0",
"@types/jest": "^29.5.11",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"typescript": "^5.3.3"
},
"jest": {
"testTimeout": 20000
}
},
"packageManager": "yarn@4.0.2"
}
63 changes: 35 additions & 28 deletions src/main.nr
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
contract EasyPrivateVoting {
use dep::protocol_types::constants::EMPTY_NULLIFIED_COMMITMENT;
use dep::protocol_types::{
abis::function_selector::FunctionSelector,
address::AztecAddress,
};
use dep::aztec::{
context::{PrivateContext, Context},
oracle::get_secret_key::get_secret_key, // used to compute nullifier
selector::compute_selector, // used to compute function selector for calling a function
state_vars::{ map::Map, public_state::PublicState,},
types::type_serialization::{ // serialization methods for using booleans and aztec addresses
bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN},
aztec_address_serialization::{AztecAddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN},
field_serialization::{ FieldSerializationMethods, FIELD_SERIALIZED_LEN},
},
types::address::{AztecAddress},
context::{PrivateContext, Context},
oracle::get_secret_key::get_secret_key, // used to compute nullifier
state_vars::{ map::Map, public_state::PublicState,},
types::type_serialization::{ // serialization methods for using booleans and aztec addresses
bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN},
address_serialization::{AddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN},
field_serialization::{ FieldSerializationMethods, FIELD_SERIALIZED_LEN},
},
};
struct Storage {
admin: PublicState<AztecAddress, AZTEC_ADDRESS_SERIALIZED_LEN>, // admin can end vote
tally: Map<PublicState<Field, FIELD_SERIALIZED_LEN>>, // we will store candidate as key and number of votes as value
voteEnded: PublicState<bool, BOOL_SERIALIZED_LEN>, // voteEnded is boolean
}
admin: PublicState<AztecAddress, AZTEC_ADDRESS_SERIALIZED_LEN>, // admin can end vote
tally: Map<PublicState<Field, FIELD_SERIALIZED_LEN>>, // we will store candidate as key and number of votes as value
voteEnded: PublicState<bool, BOOL_SERIALIZED_LEN>, // voteEnded is boolean
}
impl Storage {
fn init(context: Context) -> Self {
Storage {
admin: PublicState::new(
context,
1, // storage slot. this can be anything except 0. it is hashed, and hash on 0 = 0
AztecAddressSerializationMethods,
AddressSerializationMethods,
),
tally: Map::new(
context,
Expand All @@ -47,9 +48,9 @@ contract EasyPrivateVoting {
fn constructor(admin: AztecAddress) { // called when contract is deployed
context.call_public_function(
// we cannot update public state directly from private function but we can call public function (which queues it)
context.this_address(), // contract address whose method we want to call
compute_selector("_initialize((Field))"), // function selector
[admin.address] // parameters
context.this_address(),// contract address whose method we want to call
FunctionSelector::from_signature("_initialize((Field))"), // function selector
[admin.to_field()] // parameters
);
}
#[aztec(public)] // annotation to mark function as public and expose public context
Expand All @@ -60,12 +61,13 @@ contract EasyPrivateVoting {
#[aztec(private)] // annotation to mark function as private and expose private context
fn cast_vote(candidate: Field) {
let secret = get_secret_key(context.msg_sender()); // get secret key of caller of function
let nullifier = dep::std::hash::pedersen_hash([context.msg_sender(), secret.low, secret.high]); // compute nullifier with this secret key so others can't descrypt it
context.push_new_nullifier(nullifier, EMPTY_NULLIFIED_COMMITMENT); // push nullifier
let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret.low, secret.high]); // compute nullifier with this secret key so others can't descrypt it
context.push_new_nullifier(nullifier, 0); // push nullifier
context.call_public_function(
context.this_address(),
compute_selector("add_to_tally_public(Field)"),
[candidate]);
context.this_address(),
FunctionSelector::from_signature("add_to_tally_public(Field)"),
[candidate]
);
}

#[aztec(public)]
Expand All @@ -77,13 +79,18 @@ contract EasyPrivateVoting {

#[aztec(public)]
fn end_vote() {
assert(storage.admin.read().eq(AztecAddress::new(context.msg_sender())), "Only admin can end votes"); // assert that caller is admin
assert(storage.admin.read().eq(context.msg_sender()), "Only admin can end votes"); // assert that caller is admin
storage.voteEnded.write(true);
}
unconstrained fn get_vote(candidate: Field) -> Field {
unconstrained fn get_vote(candidate: Field) -> pub Field {
storage.tally.at(candidate).read()
}
unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, serialized_note: [Field; 0]) -> [Field; 4] {
unconstrained fn compute_note_hash_and_nullifier(
contract_address: AztecAddress,
nonce: Field,
storage_slot: Field,
serialized_note: [Field; 0]
) -> pub [Field; 4] {
[0, 0, 0, 0]
}
}
}
Loading