Skip to content

Commit 17805da

Browse files
committed
Document recursive verification example
1 parent afa349a commit 17805da

File tree

3 files changed

+44
-16
lines changed

3 files changed

+44
-16
lines changed

how-to/recursive-proofs/README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
1-
# Noir recursion
1+
# A minimal example of nested recursion
22

3-
## Install dependencies
3+
## About
44

5-
`yarn`
5+
The code in this project shows recursive verification of Noir functions.
66

7-
## Compile all the things
7+
The primary function is simply addition, and verifies the re-calculation of one path up a binary tree from two leaf nodes.
8+
A more useful application of this design would be proving the hash of data in a merkle tree (leaf nodes), up to the merkle root. Amortizing the cost of proving each hash per nested call.
89

9-
`yarn compile:all`
10+
## The circuits
11+
The function doing the calculation, in this case addition, is in the sumLib. It is used in both recursive circuits: `sum` and `recursiveLeaf`.
1012

11-
## Run main typescript
13+
## Verification
14+
Results of a call to `sum` are verified in `recursiveLeaf`, which itself also calls `sum` again. The results of the `recursiveLeaf` call are then verified in `recursiveNode`.
1215

13-
`yarn start`
16+
That is:
17+
- `recursiveNode` verifies `recursiveLeaf` artifacts
18+
- `recursiveLeaf` verifies `sum` artifacts
19+
20+
## Using this project
21+
- Install dependencies: `yarn`
22+
- Compile all the things: `yarn compile:all`
23+
- Run main typescript: `yarn start`

how-to/recursive-proofs/circuits/recurseNode/src/main.nr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ fn main(
44
verification_key: [Field; 114],
55
public_inputs: pub [Field; 5],
66
key_hash: Field,
7-
proof: [Field; 93] //109
7+
proof: [Field; 93] // 109 bytes were supposed to be required to verify recursive proofs (WIP)
88
) -> pub u64 {
99
// verify sum was computed correctly
1010
std::verify_proof(

how-to/recursive-proofs/main.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { compile, createFileManager } from '@noir-lang/noir_wasm';
99

1010
import { ProofData } from '@noir-lang/types';
1111

12+
// Helper function to get compiled Noir program
1213
async function getCircuit(name: string) {
1314
const basePath = resolve(join('./circuits', name));
1415
const fm = createFileManager(basePath);
@@ -21,32 +22,47 @@ async function getCircuit(name: string) {
2122

2223
const cores = 12;
2324

25+
// Helper function to create Noir objects
2426
async function fullNoirFromCircuit(circuitName: string): Promise<FullNoir> {
2527
const circuit: CompiledCircuit = await getCircuit(circuitName);
2628
const backend: BarretenbergBackend = new BarretenbergBackend(circuit, { threads: cores });
2729
const noir: Noir = new Noir(circuit, backend);
2830
return { circuit, backend, noir };
2931
}
3032

33+
// Type to associate related Noir objects
3134
type FullNoir = {
3235
circuit: CompiledCircuit,
3336
backend: BarretenbergBackend,
3437
noir: Noir
3538
}
3639

40+
// Calculate example sum of two leaf nodes up left branch
41+
// S3
42+
// S2 9
43+
// / \
44+
// / \
45+
// S1 4 5
46+
// / \ / \
47+
// 1 3 # #
48+
49+
3750
async function start() {
38-
const leaf: FullNoir = await fullNoirFromCircuit('sum');
39-
const recurseLeaf: FullNoir = await fullNoirFromCircuit('recurseLeaf');
40-
const recurseNode: FullNoir = await fullNoirFromCircuit('recurseNode');
51+
// Create Noir objects for each circuit
52+
const leaf: FullNoir = await fullNoirFromCircuit('sum'); // a + b = c
53+
const recurseLeaf: FullNoir = await fullNoirFromCircuit('recurseLeaf'); // verify l1 + l2 = n1, then sum n1 + n2
54+
const recurseNode: FullNoir = await fullNoirFromCircuit('recurseNode'); // verify n1 + n2 = root1
55+
56+
// Generate leaf proof artifacts (S1, addition of 1 and 3)
4157

58+
// Leaf params of left branch
4259
const leafParams = { a: 1, b: 3 };
4360
let numPubInputs = 2;
4461

45-
// Generate leaf proof artifacts
4662
let { witness, returnValue } = await leaf.noir.execute(leafParams);
4763
console.log("leaf: %d + %d = ", ...Object.values(leafParams), Number(returnValue).toString());
4864
const innerProof1: ProofData = await leaf.backend.generateProof(witness);
49-
console.log("Generating intermediate proof artifacts leaf...");
65+
console.log("Generating intermediate proof artifacts for leaf calculation...");
5066
const artifacts1 = await leaf.backend.generateRecursiveProofArtifacts(
5167
innerProof1,
5268
numPubInputs + 1 // +1 for public return
@@ -58,8 +74,9 @@ async function start() {
5874
];
5975

6076
const a = returnValue;
61-
const b = 5;
77+
const b = 5; // Sum of leaf branches beneath right node
6278

79+
// Generate node proof artifacts (S2: verify 1+3=4 proof, add 5)
6380
const nodeParams = {
6481
verification_key: artifacts1.vkAsFields,
6582
public_inputs: pub_inputs, // public, each counted individually
@@ -82,12 +99,12 @@ async function start() {
8299
pub_inputs.push(returnValue.toString()); // leaf returns sum
83100
pub_inputs.push(returnValue.toString()); // node also coded to return same value
84101

85-
// Generate and verify outer proof
102+
// Generate outer proof artifacts (S3: verify 4+5=9)
86103
const outerParams = {
87104
verification_key: artifacts2.vkAsFields,
88105
public_inputs: pub_inputs,
89106
key_hash: artifacts2.vkHash,
90-
proof: artifacts2.proofAsFields
107+
proof: artifacts2.proofAsFields // the proof size of a function that verifies another proof was expected to be 109 bytes, but was still 93
91108
};
92109

93110
console.log("Executing...");
@@ -98,6 +115,7 @@ async function start() {
98115
const resNode: boolean = await recurseNode.backend.verifyProof(outerProof);
99116
console.log("Verification", resNode ? "PASSED" : "failed");
100117

118+
// Cleanup
101119
recurseNode.backend.destroy();
102120
recurseLeaf.backend.destroy();
103121
leaf.backend.destroy();

0 commit comments

Comments
 (0)