-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32 from brolag/feature/add-circom-challenges
feat: Added new circom challenges
- Loading branch information
Showing
20 changed files
with
845 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
packages/nextjs/public/challenges/circom/challenge_3/files/KnightsKnaves.circom
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
pragma circom 2.1.6; | ||
|
||
template KnightsKnaves() { | ||
signal input A_is_knight; // 1 if A is a knight, 0 if A is a knave | ||
signal input B_is_knight; // 1 if B is a knight, 0 if B is a knave | ||
|
||
// Intermediate signals for A's statement | ||
signal A_statement_part1; | ||
signal A_statement_part2; | ||
|
||
// A says "B is a knave" | ||
A_statement_part1 <== A_is_knight * (1 - B_is_knight); | ||
A_statement_part2 <== (1 - A_is_knight) * B_is_knight; | ||
signal A_statement_valid; | ||
A_statement_valid <== A_statement_part1 + A_statement_part2; | ||
|
||
// Intermediate signals for B's statement | ||
signal B_statement_part1; | ||
signal B_statement_part2; | ||
signal B_statement_part1_1; | ||
signal B_statement_part1_2; | ||
signal B_statement_part1_3; | ||
signal B_statement_part2_1; | ||
signal B_statement_part2_2; | ||
signal B_statement_part2_3; | ||
|
||
// If B is a knight (1), then A and B must be of opposite types | ||
//B_statement_part1 <== B_is_knight * (A_is_knight * (1 - B_is_knight) + (1 - A_is_knight) * B_is_knight); | ||
B_statement_part1_1 <== A_is_knight * (1 - B_is_knight); | ||
B_statement_part1_2 <== (1 - A_is_knight) * B_is_knight; | ||
B_statement_part1_3 <== (B_statement_part1_1 + B_statement_part1_2); | ||
B_statement_part1 <== B_is_knight * B_statement_part1_3; | ||
|
||
// If B is a knave (0), then A and B must be of the same type | ||
//B_statement_part2 <== (1 - B_is_knight) * (A_is_knight * B_is_knight + (1 - A_is_knight) * (1 - B_is_knight)); | ||
B_statement_part2_1 <== A_is_knight * B_is_knight; | ||
B_statement_part2_2 <== (1 - A_is_knight) * (1 - B_is_knight); | ||
B_statement_part2_3 <== B_statement_part2_1 + B_statement_part2_2; | ||
B_statement_part2 <== (1 - B_is_knight) * B_statement_part2_3; | ||
|
||
signal B_statement_valid; | ||
B_statement_valid <== B_statement_part1 + B_statement_part2; | ||
|
||
// Enforce that both statements must be valid | ||
signal output is_consistent; | ||
is_consistent <== A_statement_valid * B_statement_valid; | ||
|
||
// Enforce that is_consistent must be 1 | ||
// This makes sure the circuit will only accept valid proofs | ||
is_consistent * (is_consistent - 1) === 0; // This ensures is_consistent is either 0 or 1 | ||
is_consistent === 1; // This ensures is_consistent is 1 | ||
|
||
} | ||
|
||
component main = KnightsKnaves(); |
54 changes: 54 additions & 0 deletions
54
packages/nextjs/public/challenges/circom/challenge_3/files/abi.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
[ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "uint256[2]", | ||
"name": "_pA", | ||
"type": "uint256[2]" | ||
}, | ||
{ | ||
"internalType": "uint256[2][2]", | ||
"name": "_pB", | ||
"type": "uint256[2][2]" | ||
}, | ||
{ | ||
"internalType": "uint256[2]", | ||
"name": "_pC", | ||
"type": "uint256[2]" | ||
}, | ||
{ | ||
"internalType": "uint256[1]", | ||
"name": "_pubSignals", | ||
"type": "uint256[1]" | ||
} | ||
], | ||
"name": "sendProof", | ||
"outputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "circomVeriferAddress", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "nonpayable", | ||
"type": "constructor" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "publicInput", | ||
"outputs": [ | ||
{ | ||
"internalType": "uint256", | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
} | ||
] |
151 changes: 151 additions & 0 deletions
151
packages/nextjs/public/challenges/circom/challenge_3/files/custom.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
const NETWORK_ID = 11155111 | ||
|
||
const MY_CONTRACT_ADDRESS = "0xCCa8c40aeA7Ef91249725C53e86764FBA527d845" | ||
const MY_CONTRACT_ABI_PATH = "./abi.json" | ||
var my_contract | ||
|
||
var accounts | ||
var web3 | ||
|
||
function metamaskReloadCallback() { | ||
window.ethereum.on('accountsChanged', (accounts) => { | ||
document.getElementById("web3_message").textContent="Se cambió el account, refrescando..."; | ||
window.location.reload() | ||
}) | ||
window.ethereum.on('networkChanged', (accounts) => { | ||
document.getElementById("web3_message").textContent="Se el network, refrescando..."; | ||
window.location.reload() | ||
}) | ||
} | ||
|
||
const getWeb3 = async () => { | ||
return new Promise((resolve, reject) => { | ||
if(document.readyState=="complete") | ||
{ | ||
if (window.ethereum) { | ||
const web3 = new Web3(window.ethereum) | ||
window.location.reload() | ||
resolve(web3) | ||
} else { | ||
reject("must install MetaMask") | ||
document.getElementById("web3_message").textContent="Error: Porfavor conéctate a Metamask"; | ||
} | ||
}else | ||
{ | ||
window.addEventListener("load", async () => { | ||
if (window.ethereum) { | ||
const web3 = new Web3(window.ethereum) | ||
resolve(web3) | ||
} else { | ||
reject("must install MetaMask") | ||
document.getElementById("web3_message").textContent="Error: Please install Metamask"; | ||
} | ||
}); | ||
} | ||
}); | ||
}; | ||
|
||
const getContract = async (web3, address, abi_path) => { | ||
const response = await fetch(abi_path); | ||
const data = await response.json(); | ||
|
||
const netId = await web3.eth.net.getId(); | ||
contract = new web3.eth.Contract( | ||
data, | ||
address | ||
); | ||
return contract | ||
} | ||
|
||
async function loadDapp() { | ||
metamaskReloadCallback() | ||
document.getElementById("web3_message").textContent="Please connect to Metamask" | ||
var awaitWeb3 = async function () { | ||
web3 = await getWeb3() | ||
web3.eth.net.getId((err, netId) => { | ||
if (netId == NETWORK_ID) { | ||
var awaitContract = async function () { | ||
my_contract = await getContract(web3, MY_CONTRACT_ADDRESS, MY_CONTRACT_ABI_PATH) | ||
document.getElementById("web3_message").textContent="You are connected to Metamask" | ||
onContractInitCallback() | ||
web3.eth.getAccounts(function(err, _accounts){ | ||
accounts = _accounts | ||
if (err != null) | ||
{ | ||
console.error("An error occurred: "+err) | ||
} else if (accounts.length > 0) | ||
{ | ||
onWalletConnectedCallback() | ||
document.getElementById("account_address").style.display = "block" | ||
} else | ||
{ | ||
document.getElementById("connect_button").style.display = "block" | ||
} | ||
}); | ||
}; | ||
awaitContract(); | ||
} else { | ||
document.getElementById("web3_message").textContent="Please connect to Scroll Testnet"; | ||
} | ||
}); | ||
}; | ||
awaitWeb3(); | ||
} | ||
|
||
async function connectWallet() { | ||
await window.ethereum.request({ method: "eth_requestAccounts" }) | ||
accounts = await web3.eth.getAccounts() | ||
onWalletConnectedCallback() | ||
} | ||
|
||
loadDapp() | ||
|
||
const onContractInitCallback = async () => { | ||
var publicInput = await my_contract.methods.publicInput().call() | ||
var contract_state = "Public input: " + publicInput | ||
console.log(contract_state); | ||
document.getElementById("contract_state").textContent = contract_state; | ||
} | ||
|
||
const onWalletConnectedCallback = async () => { | ||
} | ||
|
||
|
||
//// Functions //// | ||
|
||
const sendProof = async (a, b) => { | ||
document.getElementById("web3_message").textContent="Generating proof..."; | ||
|
||
const { proof, publicSignals } = await snarkjs.groth16.fullProve( { A_is_knight: a, B_is_knight: b}, "../zk_artifacts/myCircuit.wasm", "../zk_artifacts/myCircuit_final.zkey"); | ||
|
||
const vkey = await fetch("../zk_artifacts/verification_key.json").then( function(res) { | ||
return res.json(); | ||
}); | ||
|
||
const res = await snarkjs.groth16.verify(vkey, publicSignals, proof); | ||
|
||
pA = proof.pi_a | ||
pA.pop() | ||
pB = proof.pi_b | ||
pB.pop() | ||
pC = proof.pi_c | ||
pC.pop() | ||
|
||
console.log(pA); | ||
console.log(pB); | ||
console.log(pC); | ||
console.log(publicSignals); | ||
|
||
document.getElementById("web3_message").textContent="Proof generated please confirm transaction."; | ||
|
||
const result = await my_contract.methods.sendProof(pA, pB, pC, publicSignals) | ||
.send({ from: accounts[0], gas: 0, value: 0 }) | ||
.on('transactionHash', function(hash){ | ||
document.getElementById("web3_message").textContent="Executing..."; | ||
}) | ||
.on('receipt', function(receipt){ | ||
document.getElementById("web3_message").textContent="Success."; }) | ||
.catch((revertReason) => { | ||
console.log("ERROR! Transaction reverted: " + revertReason.receipt.transactionHash) | ||
}); | ||
} |
Oops, something went wrong.