Skip to content

Commit c65e685

Browse files
committed
Circom for advent of code day 2
1 parent aaec857 commit c65e685

File tree

8 files changed

+400
-17
lines changed

8 files changed

+400
-17
lines changed

circom/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
build/
22
proofs/
3-
inputs/*.wtns
3+
inputs/*.wtns
4+
inputs/*.wtns.json

circom/Makefile

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
all: multiplier2
22

3-
.PHONY: verify/% contracts test
3+
.PHONY: contracts test
4+
5+
CIRCUITS := multiplier2 advent2
46

57
# Build verifying contracts
6-
contracts: contracts/multiplier2.sol
8+
contracts: $(foreach circuit,$(CIRCUITS),contracts/$(circuit).sol)
79

810
# Build circuit, create witness, create proof, and verify it
911
multiplier2: verify/multiplier2
12+
advent2: verify/advent2
1013

1114
# Do not delete intermediate files
1215
.SECONDARY:
@@ -15,8 +18,9 @@ multiplier2: verify/multiplier2
1518
build/%.r1cs: circuits/%.circom
1619
@echo Building $@...
1720
mkdir -p build/
18-
circom $< --r1cs --wasm --sym --c -o build/
19-
@echo
21+
circom $< --r1cs --wasm --sym --c -l ../node_modules/circomlib/circuits -o build/
22+
yarn -s snarkjs r1cs export json build/$*.r1cs build/$*.r1cs.json
23+
@echo
2024

2125
# Creates a witness out of the circuit and input
2226
inputs/%.wtns: build/%.r1cs inputs/%.json
@@ -25,35 +29,39 @@ inputs/%.wtns: build/%.r1cs inputs/%.json
2529
build/$*_js/$*.wasm \
2630
inputs/$*.json \
2731
inputs/$*.wtns
32+
yarn -s snarkjs wtns export json inputs/$*.wtns inputs/$*.wtns.json
33+
@echo
2834

2935
# General phase 1 ceremony of powers of tau (trusted setup)
3036
proofs/pot12_0001.ptau:
3137
@echo Powers of tau ceremony phase 1...
3238
mkdir -p proofs
33-
yarn snarkjs powersoftau new bn128 12 proofs/pot12_0000.ptau -v
34-
yarn snarkjs powersoftau contribute proofs/pot12_0000.ptau proofs/pot12_0001.ptau --name="First contribution"
39+
yarn -s snarkjs powersoftau new bn128 12 proofs/pot12_0000.ptau -v
40+
yarn -s snarkjs powersoftau contribute proofs/pot12_0000.ptau proofs/pot12_0001.ptau --name="First contribution"
3541
@echo
3642

3743
# Circuit-specific phase 2 ceremony of powers of tau (trusted setup)
3844
proofs/%/verification_key.json: proofs/pot12_0001.ptau build/%.r1cs
3945
@echo Phase two of the ceremony...
4046
mkdir -p proofs/$*
41-
yarn snarkjs powersoftau prepare phase2 proofs/pot12_0001.ptau proofs/$*/pot12.ptau
42-
yarn snarkjs groth16 setup build/multiplier2.r1cs proofs/$*/pot12.ptau proofs/$*/key_0000.zkey
43-
yarn snarkjs zkey contribute proofs/$*/key_0000.zkey proofs/$*/key_0001.zkey --name="First contribution"
44-
yarn snarkjs zkey export verificationkey proofs/$*/key_0001.zkey proofs/$*/verification_key.json
47+
yarn -s snarkjs powersoftau prepare phase2 proofs/pot12_0001.ptau proofs/$*/pot12.ptau
48+
yarn -s snarkjs groth16 setup build/$*.r1cs proofs/$*/pot12.ptau proofs/$*/key_0000.zkey
49+
yarn -s snarkjs zkey contribute proofs/$*/key_0000.zkey proofs/$*/key_0001.zkey --name="First contribution"
50+
yarn -s snarkjs zkey export verificationkey proofs/$*/key_0001.zkey proofs/$*/verification_key.json
4551
@echo
4652

4753
# Create a verifier contract out of a verification key
4854
contracts/%.sol: proofs/%/verification_key.json
4955
@echo Generating verifier contract...
5056
mkdir -p contracts/
51-
yarn snarkjs zkey export solidityverifier proofs/$*/key_0001.zkey contracts/$*.sol
57+
yarn -s snarkjs zkey export solidityverifier proofs/$*/key_0001.zkey contracts/$*.sol
5258

5359
# Create proof for a given witness, given the verification key generated in phase 2
5460
proofs/%/proof.json: proofs/%/verification_key.json inputs/%.wtns
5561
@echo Generating proof...
56-
yarn snarkjs groth16 prove proofs/$*/key_0001.zkey inputs/$*.wtns proofs/$*/proof.json proofs/$*/public.json
62+
yarn -s snarkjs groth16 prove proofs/$*/key_0001.zkey inputs/$*.wtns proofs/$*/proof.json proofs/$*/public.json
63+
@echo Output:
64+
@jq -c '.' proofs/$*/public.json
5765
@echo
5866

5967
# Create proof to be fed into verifier contract
@@ -65,11 +73,11 @@ proofs/%/solidity-args.json: proofs/%/proof.json
6573
# Verify the proof
6674
verify/%: proofs/%/proof.json
6775
@echo Verifying proof for $*...
68-
yarn snarkjs groth16 verify proofs/$*/verification_key.json proofs/$*/public.json proofs/$*/proof.json
76+
yarn -s snarkjs groth16 verify proofs/$*/verification_key.json proofs/$*/public.json proofs/$*/proof.json
6977
@echo
7078

7179
# Test verifying contracts
72-
test: proofs/multiplier2/solidity-args.json
80+
test: $(foreach circuit,$(CIRCUITS),proofs/$(circuit)/solidity-args.json)
7381
@echo Running hardhat tests...
74-
yarn hardhat test
82+
yarn -s hardhat test
7583
@echo

circom/circuits/advent2.circom

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
pragma circom 2.1.1;
2+
3+
include "comparators.circom";
4+
5+
/*
6+
Rock=0
7+
Paper=1
8+
Scissors=2
9+
10+
x | y | out
11+
-----------
12+
0 | 2 | 0
13+
0 | 0 | 1
14+
0 | 1 | 2
15+
1 | 0 | 0
16+
1 | 1 | 1
17+
1 | 2 | 2
18+
2 | 1 | 0
19+
2 | 2 | 1
20+
2 | 0 | 2
21+
*/
22+
23+
// Checks if input x is a valid rock-paper-scissors value (0,1,2)
24+
template AssertIsRPS() {
25+
signal input x;
26+
signal isRP <== (x-0) * (x-1);
27+
isRP * (x-2) === 0;
28+
}
29+
30+
// Returns the score for a single round, given the plays by x and y
31+
template Round() {
32+
signal input x, y;
33+
signal output out;
34+
35+
// ensure that each input is within 0,1,2
36+
AssertIsRPS()(x);
37+
AssertIsRPS()(y);
38+
39+
// check if match was a draw
40+
signal isDraw <== IsEqual()([x, y]);
41+
42+
signal diffYX <== (y+3)-x;
43+
44+
// y wins if y-x = 1 mod 3
45+
signal yWins1 <== (diffYX-1) * (diffYX-4);
46+
signal yWins <== IsZero()(yWins1);
47+
48+
// x wins if y-x = 2 mod 3
49+
signal xWins1 <== (diffYX-2) * (diffYX-5);
50+
signal xWins <== IsZero()(xWins1);
51+
52+
// check that exactly one of xWins, yWins, isDraw is true
53+
// we probably can do without these constraints
54+
signal xOrYWins <== (xWins - 1) * (yWins - 1);
55+
xOrYWins * (isDraw - 1) === 0;
56+
xWins + yWins + isDraw === 1;
57+
58+
// score is 6 if y wins, 3 if draw, 0 if x wins
59+
// plus 1, 2, 3 depending on the choice of RPS
60+
out <== yWins * 6 + isDraw * 3 + y + 1;
61+
}
62+
63+
// Returns the score over all matches in a game with n rounds
64+
// Inputs are the plays by x and y
65+
template Game(n) {
66+
signal input xs[n];
67+
signal input ys[n];
68+
signal scores[n];
69+
signal output out;
70+
71+
var score = 0;
72+
for (var i = 0; i < n; i++) {
73+
scores[i] <== Round()(xs[i], ys[i]);
74+
score += scores[i];
75+
}
76+
77+
out <== score;
78+
}
79+
80+
component main = Game(3);

0 commit comments

Comments
 (0)