Skip to content

Commit

Permalink
implement canon addr sig check circuit, verifier, sdk wrapper (#433)
Browse files Browse the repository at this point in the history
* implement circuit

* build circuit

* test and add snap method for sig

* add frontend-sdk function to gen proof

* upload circuit artifacts

* changesets

* add nonce to canonAddrSigCheck circuit

* snap manifest

* fix formatting

* fix comment
  • Loading branch information
Sladuca authored Sep 5, 2023
1 parent cea0c32 commit 589e023
Show file tree
Hide file tree
Showing 33 changed files with 878 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-houses-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nocturne-xyz/contracts": patch
---

add `CanonAddrSigCheckVerifier` contract
5 changes: 5 additions & 0 deletions .changeset/silly-frogs-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nocturne-xyz/snap": patch
---

add RPC method for generating canon addr sig
7 changes: 7 additions & 0 deletions .changeset/sixty-houses-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@nocturne-xyz/frontend-sdk": patch
"@nocturne-xyz/local-prover": patch
"@nocturne-xyz/core": patch
---

add sdk support for generating CanonAddrSigCheck proofs
5 changes: 5 additions & 0 deletions .changeset/spicy-avocados-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nocturne-xyz/circuits": patch
---

add new circuit `CanonAddrSigCheck` that can be used to prove knowledge of keys for given canonical address
2 changes: 1 addition & 1 deletion apps/snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Nocturne Snap",
"proposedName": "Nocturne Snap",
"source": {
"shasum": "U/ZPYG036Gm59X3An8+4f+l3rF7lUdRBSXWBNf0FD78=",
"shasum": "CXkeM5G9r3g7+XrmTPtVbHJFXEif5F8rNfRoMUzzPKE=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
14 changes: 14 additions & 0 deletions apps/snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
parseObjectValues,
signOperation,
assertAllRpcMethodsHandled,
CANON_ADDR_SIG_CHECK_PREFIX,
} from "@nocturne-xyz/core";
import * as JSON from "bigint-json-serialization";
import { ethers } from "ethers";
import { makeSignOperationContent } from "./utils/display";
import { loadNocturneConfigBuiltin } from "@nocturne-xyz/config";
import { poseidonBN } from "@nocturne-xyz/crypto-utils";

// To build locally, invoke `yarn build:local` from snap directory
// Sepolia
Expand Down Expand Up @@ -79,6 +81,18 @@ async function handleRpcRequest({
vk: viewer.vk,
vkNonce: viewer.vkNonce,
};
case "nocturne_getCanonAddrSigCheckProofInputs":
const msg = poseidonBN([CANON_ADDR_SIG_CHECK_PREFIX, params.nonce]);
const sig = signer.sign(msg);
const vkNonce = signer.vkNonce;
const spendPubkey = signer.spendPk;
const canonAddr = signer.canonicalAddress();
return {
canonAddr,
sig,
spendPubkey,
vkNonce,
};
case "nocturne_signOperation":
console.log("Request params: ", request.params);

Expand Down
22 changes: 22 additions & 0 deletions circuit-artifacts/canonAddrSigCheck/canonAddrSigCheck_cpp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
CC=g++
CFLAGS=-std=c++11 -O3 -I.
DEPS_HPP = circom.hpp calcwit.hpp fr.hpp
DEPS_O = main.o calcwit.o fr.o fr_asm.o

ifeq ($(shell uname),Darwin)
NASM=nasm -fmacho64 --prefix _
endif
ifeq ($(shell uname),Linux)
NASM=nasm -felf64
endif

all: canonAddrSigCheck

%.o: %.cpp $(DEPS_HPP)
$(CC) -c $< $(CFLAGS)

fr_asm.o: fr.asm
$(NASM) fr.asm -o fr_asm.o

canonAddrSigCheck: $(DEPS_O) canonAddrSigCheck.o
$(CC) -o canonAddrSigCheck *.o -lgmp
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"protocol": "groth16",
"curve": "bn128",
"nPublic": 2,
"vk_alpha_1": [
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
"1"
],
"vk_beta_2": [
[
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
],
[
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"773020532580825197989265700683499343769904901528688421551138914726744641180",
"8293403394473099785006220829731294292309334277329635922514577348444877204455"
],
[
"8044298410607931596843420349541257429151935437174909763540021311308466536301",
"17214381066153793863275327145188716040063142813916029058922963729943312663323"
],
[
"1",
"0"
]
],
"vk_alphabeta_12": [
[
[
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
],
[
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
],
[
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
]
],
[
[
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
],
[
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
],
[
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
]
]
],
"IC": [
[
"4832813700246065920361343021419859188951987917247921272000554979262446849501",
"16450982492709346235822465585897720176511819063596563345522452720051071864672",
"1"
],
[
"20319267411373749280521656549635790467688687986098419353391917503577446154512",
"17574942179666147033145072864414125540440799097149046608123758211273599911170",
"1"
],
[
"17449537628454795474707997846067025590393693011235612812267573590657605090044",
"16721453092532359171509851342766105079684512390183817843689473273663565221671",
"1"
]
]
}
Binary file not shown.
1 change: 1 addition & 0 deletions fixtures/canonAddrSigCheckProof.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"proof":{"pi_a":["4707566568477662226701048704629002296898023495689302474085085543854193803155","3644575967738185505850689153930594197798302000091737453074352963009621583047","1"],"pi_b":[["13069141789356215556738799393349390032904395438451693951284966024185000982701","16413079359372682889686551964213736164909267325081402914478067411060909601738"],["10662132772867170602735388807233470982369982452803154206295065507017214400127","4210609573482297197474333202124807106129386536279608053368214238189911285716"],["1","0"]],"pi_c":["4336617563514886771836809062099125132568962461354180077456839313813411275943","6202904228419388614700373200548865108297023268079905783649845080424671268049","1"],"protocol":"groth16","curve":"bn128"},"publicSignals":["6590372629931178525044320278222256515723582191188933114746797360106155515468n","1453n"]}
55 changes: 55 additions & 0 deletions packages/circuits/circuits/canonAddrSigCheck.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
pragma circom 2.1.0;

include "lib.circom";
include "include/babyjub.circom";

//@ensures(1) `compressedCanonAddr` and the sign bit from `nonceAndSignBit` are a valid canonical address
//@ensures(2) the prover can produce a valid signature of the message
// `CANONICAL_ADDRESS_REGISTRY_PREFIX | nonce` using the
// spending key corresponding the canonical address given in public inputs
template CanonAddrSigCheck() {
// *** PUBLIC INPUTS ***
signal input compressedCanonAddrY;
signal input nonceAndSignBit;

// *** WITNESS ***
// signature used to prove knowledge of spending key
signal input sig[2];
signal input spendPubkey[2];
signal input vkNonce;

signal nonceAndSignBitBits[65] <== Num2Bits(65)(nonceAndSignBit);
signal signBit <== nonceAndSignBitBits[64];
signal nonce <== nonceAndSignBit - (1 << 64) * signBit;

BabyCheck()(spendPubkey[0], spendPubkey[1]);
IsOrderL()(spendPubkey[0], spendPubkey[1]);

// keccak256("nocturne-canonical-address-registry") % l (baby jubjub scalar field order)
var CANONICAL_ADDRESS_REGISTRY_PREFIX = 116601516046334945492116181810016234440204750152070409904129749171886331002;
signal msg <== Poseidon(2)([CANONICAL_ADDRESS_REGISTRY_PREFIX, nonce]);

//@lemma(1) prover can generate valid sig for `CANONICAL_ADDRESS_REGISTRY_PREFIX | nonce` against spendPubkey
//@argument `SigVerify.requires(1)` is guaranteed by checks above. lemma follows from `SigVerify.ensures(1)`
SigVerify()(spendPubkey, msg, sig);

//@satisfies(2)
//@argument `VKDerivation.requires(1)` is guranteed by checks above.
// `VKDerivation.ensures(3, 1)` => vkBits is the LE repr of the correct VK derived from spendPubkey and vkNonce
// => `CanonAddr.requires(1)` is satisfied. Then, (2) follows from `CanonAddr.ensures(2)` and `@lemma(1)`
component vkDerivation = VKDerivation();
vkDerivation.spendPubkey <== spendPubkey;
vkDerivation.vkNonce <== vkNonce;
signal vkBits[251] <== vkDerivation.vkBits;
signal canonAddr[2] <== CanonAddr()(vkBits);

//@satisfies(1)
//@argument `CanonAddr` above ensures that canonAddr is a valid canonical address.
// the checks below ensure that it matches the one given in PIs. Therefore (1) is satisfied.
component compressor = CompressPoint();
compressor.in <== canonAddr;
compressedCanonAddrY === compressor.y;
signBit === compressor.sign;
}

component main { public [compressedCanonAddrY, nonceAndSignBit] } = CanonAddrSigCheck();
1 change: 1 addition & 0 deletions packages/circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"build:deps": "../../scripts/install_base_deps.sh && ./scripts/install_deps.sh",
"build:joinsplit": "scripts/joinsplit/build.sh",
"build:subtreeupdate": "scripts/subtreeupdate/build.sh",
"build:canonAddrSigCheck": "scripts/canonAddrSigCheck/build.sh",
"clean": "",
"download-big-ptau": "scripts/download_big_ptau.sh",
"lint": "",
Expand Down
1 change: 1 addition & 0 deletions packages/circuits/scripts/build_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ set -e
DIR=$(dirname "$0")
$DIR/joinsplit/build.sh
$DIR/subtreeupdate/build.sh
$DIR/canonAddrSigCheck/build.sh
83 changes: 83 additions & 0 deletions packages/circuits/scripts/canonAddrSigCheck/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/bash
CIRCUIT_NAME=canonAddrSigCheck
SCRIPT_DIR=$(dirname "$0")
ROOT_SCRIPT_DIR="$SCRIPT_DIR/../"
ROOT_DIR="$SCRIPT_DIR/../../../../"
CIRCUIT_ARTIFACTS_DIR="$ROOT_DIR/circuit-artifacts"
PHASE1_PATH="$SCRIPT_DIR/../../data/powersOfTau28_hez_final_15.ptau"
CIRCUIT_PATH="$SCRIPT_DIR/../../circuits/$CIRCUIT_NAME.circom"
BUILD_DIR="$CIRCUIT_ARTIFACTS_DIR/$CIRCUIT_NAME"
OUTPUT_DIR="$BUILD_DIR"/"$CIRCUIT_NAME"_cpp
CONTRACTS_DIR="$ROOT_DIR/packages/contracts/contracts"

if [ -f "$PHASE1_PATH" ]; then
echo "Found Phase 1 ptau file"
else
echo "No Phase 1 ptau file found. Exiting..."
exit 1
fi

if [ ! -d "$BUILD_DIR" ]; then
echo "No build directory found. Creating build directory..."
mkdir -p "$BUILD_DIR"
fi

echo "****COMPILING CIRCUIT****"
start=`date +%s`
circom "$CIRCUIT_PATH" --r1cs --wasm --sym --c --wat --output "$BUILD_DIR"
end=`date +%s`
echo "DONE ($((end-start))s)"

# echo "****GENERATING WITNESS FOR SAMPLE INPUT****"
# start=`date +%s`
# node "$BUILD_DIR"/"$CIRCUIT_NAME"_js/generate_witness.js "$BUILD_DIR"/"$CIRCUIT_NAME"_js/"$CIRCUIT_NAME".wasm input_joinsplit.json "$BUILD_DIR"/witness.wtns
# end=`date +%s`
# echo "DONE ($((end-start))s)"

echo "****GENERATING ZKEY 0****"
start=`date +%s`
npx snarkjs groth16 setup "$BUILD_DIR"/"$CIRCUIT_NAME".r1cs "$PHASE1_PATH" "$OUTPUT_DIR"/"$CIRCUIT_NAME"_0.zkey
end=`date +%s`
echo "DONE ($((end-start))s)"

echo "****CONTRIBUTE TO THE PHASE 2 CEREMONY****"
start=`date +%s`
echo "test" | npx snarkjs zkey contribute "$OUTPUT_DIR"/"$CIRCUIT_NAME"_0.zkey "$OUTPUT_DIR"/"$CIRCUIT_NAME"_1.zkey --name="1st Contributor Name"
end=`date +%s`
echo "DONE ($((end-start))s)"

echo "****GENERATING FINAL ZKEY****"
start=`date +%s`
npx snarkjs zkey beacon "$OUTPUT_DIR"/"$CIRCUIT_NAME"_1.zkey "$OUTPUT_DIR"/"$CIRCUIT_NAME".zkey 0102030405060708090a0b0c0d0e0f101112231415161718221a1b1c1d1e1f 10 -n="Final Beacon phase2"
end=`date +%s`
echo "DONE ($((end-start))s)"

echo "****VERIFYING FINAL ZKEY****"
start=`date +%s`
npx snarkjs zkey verify "$BUILD_DIR"/"$CIRCUIT_NAME".r1cs "$PHASE1_PATH" "$OUTPUT_DIR"/"$CIRCUIT_NAME".zkey
end=`date +%s`
echo "DONE ($((end-start))s)"

echo "****EXPORTING VKEY****"
start=`date +%s`
npx snarkjs zkey export verificationkey "$OUTPUT_DIR"/"$CIRCUIT_NAME".zkey "$OUTPUT_DIR"/vkey.json
end=`date +%s`
echo "DONE ($((end-start))s)"

# echo "****GENERATING PROOF FOR SAMPLE INPUT****"
# start=`date +%s`
# npx snarkjs groth16 prove "$BUILD_DIR"/"$CIRCUIT_NAME".zkey "$BUILD_DIR"/witness.wtns "$BUILD_DIR"/proof.json "$BUILD_DIR"/public.json
# end=`date +%s`
# echo "DONE ($((end-start))s)"

# echo "****VERIFYING PROOF FOR SAMPLE INPUT****"
# start=`date +%s`
# npx snarkjs groth16 verify "$BUILD_DIR"/vkey.json "$BUILD_DIR"/public.json "$BUILD_DIR"/proof.json
# end=`date +%s`
# echo "DONE ($((end-start))s)"

echo "****EXPORTING SOLIDITY SMART CONTRACT****"
start=`date +%s`
yarn ts-node "$ROOT_SCRIPT_DIR/genSolidityVerifier.ts" "$OUTPUT_DIR/vkey.json" CanonAddrSigCheckVerifier
end=`date +%s`
echo "DONE ($((end-start))s)"
Loading

0 comments on commit 589e023

Please sign in to comment.