Skip to content

Instantly share code, notes, and snippets.

@emptycrown
Last active June 3, 2022 22:20
Show Gist options
  • Save emptycrown/d3c608af5556e17398d8fe9e1c9e5499 to your computer and use it in GitHub Desktop.
Save emptycrown/d3c608af5556e17398d8fe9e1c9e5499 to your computer and use it in GitHub Desktop.
Completed circuit for a ZK Mastermind implementation: https://jessezhang.org/mastermind
pragma circom 2.0.3;
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
template Mastermind () {
var n = 4;
signal input guess[n];
signal input answer[n];
signal input ansHash;
signal black[n];
signal white[n];
signal output result[2];
component iszg[n];
component iszy[n];
component lt[n];
// Check if hash is correct
component hash = Poseidon(n);
for(var i=0; i<n; i++) {
hash.inputs[i] <== answer[i];
}
hash.out === ansHash;
// Check that all answers are less than 6 (only six total colors)
for(var i=0; i<n; i++) {
lt[i] = LessThan(252);
lt[i].in[0] <== answer[i];
lt[i].in[1] <== 6;
lt[i].out === 1;
}
// Determine if each guess matches the answer
for(var i=0; i<n; i++) {
iszg[i] = IsZero();
iszg[i].in <== guess[i] - answer[i];
iszg[i].out ==> black[i];
}
// Determine if each guess is present somewhere in the answer via product
signal prod[n][n+1];
for(var i=0; i<n; i++) {
iszy[i] = IsZero();
prod[i][0] <== 1;
for(var j=0; j<n; j++) {
prod[i][j+1] <== prod[i][j] * (guess[i] - answer[j]);
}
iszy[i].in <== prod[i][n];
iszy[i].out ==> white[i];
}
// When black is present, the corresponding white is useless
signal temp[n];
for(var i=0; i<n; i++) {
temp[i] <== white[i] * (1 - black[i]);
}
// Count up the black and white pins and store in result
var sum0 = 0;
var sum1 = 0;
for(var i=0; i<n; i++) {
sum0 += black[i];
sum1 += temp[i];
}
result[0] <== sum0;
result[1] <== sum1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment