# How to use recursion on NoirJS

This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that:

- You already have a NoirJS app. If you don't, please visit the NoirJS tutorial and the reference.
- You are familiar with what are recursive proofs and you have read the recursion explainer
- You already built a recursive circuit following the reference, and understand how it works.

It is also assumed that you're not using `noir_wasm`

for compilation, and instead you've used `nargo compile`

to generate the `json`

you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`

.

As you've read in the explainer, a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit.

While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly.

In short:

`noir_js`

generates*only*final proofs`backend_barretenberg`

generates both types of proofs

In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following:

`main`

: a circuit of type`assert(x != y)`

, where`main`

is marked with a`#[recursive]`

attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit.`recursive`

: a circuit that verifies`main`

For a full example on how recursive proofs work, please refer to the noir-examples repository. We will *not* be using it as a reference for this guide.

## Step 1: Setup

In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`

. Then you feed it to the `noir_js`

interface.

For recursion, this doesn't happen, and the only need for `noir_js`

is only to `execute`

a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend`

object.

It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency:

`const backend = new Backend(circuit, { threads: 8 })`

You can use the `os.cpus()`

object in `nodejs`

or `navigator.hardwareConcurrency`

on the browser to make the most out of those glorious cpu cores

## Step 2: Generating the witness and the proof for `main`

After instantiating the backend, you should also instantiate `noir_js`

. We will use it to execute the circuit and get the witness.

`const noir = new Noir(circuit, backend)`

const { witness } = noir.execute(input)

With this witness, you are now able to generate the intermediate proof for the main circuit:

`const { proof, publicInputs } = await backend.generateProof(witness)`

Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why!

In this case, you can imagine that Alice (running the `main`

circuit) is proving something to Bob (running the `recursive`

circuit), and Bob is verifying her proof within his proof.

With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain.

## Step 3 - Verification and proof artifacts

Optionally, you are able to verify the intermediate proof:

`const verified = await backend.verifyProof({ proof, publicInputs })`

This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit:

`const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount)`

This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs`

length, the backend interface doesn't currently abstract it away.

The `proofAsFields`

has a constant size `[Field; 93]`

and verification keys in Barretenberg are always `[Field; 114]`

.

One common mistake is to forget *who* makes this call.

In a situation where Alice is generating the `main`

proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything!

Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main`

circuit backend. This way, Alice has to provide a valid proof for the correct `main`

circuit.

## Step 4 - Recursive proof generation

With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend`

(with the recursive circuit) to generate it:

`const recursiveInputs = {`

verification_key: vkAsFields, // array of length 114

proof: proofAsFields, // array of length 93 + size of public inputs

publicInputs: [mainInput.y], // using the example above, where `y` is the only public input

key_hash: vkHash,

}

const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now!

const { proof, publicInputs } = backend.generateProof(witness)

const verified = backend.verifyProof({ proof, publicInputs })

You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way!

Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example:

`const circuits = {`

main: mainJSON,

recursive: recursiveJSON

}

const backends = {

main: new BarretenbergBackend(circuits.main),

recursive: new BarretenbergBackend(circuits.recursive)

}

const noir_programs = {

main: new Noir(circuits.main, backends.main),

recursive: new Noir(circuits.recursive, backends.recursive)

}

This allows you to neatly call exactly the method you want without conflicting names:

`// Alice runs this 👇`

const { witness: mainWitness } = await noir_programs.main.execute(input)

const proof = await backends.main.generateProof(mainWitness)

// Bob runs this 👇

const verified = await backends.main.verifyProof(proof)

const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts(

proof,

numPublicInputs,

);

const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs)