From 3c29fda0adbd440da484fcab35f303fcd0ee9714 Mon Sep 17 00:00:00 2001
From: TomAFrench <tom@tomfren.ch>
Date: Wed, 25 Oct 2023 17:05:24 +0000
Subject: [PATCH 1/5] feat(noir_js): allow providing foreign call handlers in
 noirJS

---
 tooling/noir_js/src/program.ts            |  8 ++++----
 tooling/noir_js/src/witness_generation.ts | 12 +++++++-----
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts
index bf48e15fcad..f09fdb34253 100644
--- a/tooling/noir_js/src/program.ts
+++ b/tooling/noir_js/src/program.ts
@@ -2,13 +2,13 @@
 import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types';
 import { generateWitness } from './witness_generation.js';
 import initAbi, { abiDecode, InputMap, InputValue } from '@noir-lang/noirc_abi';
-import initACVM, { compressWitness } from '@noir-lang/acvm_js';
+import initACVM, { compressWitness, ForeignCallHandler } from '@noir-lang/acvm_js';
 
 export class Noir {
   constructor(
     private circuit: CompiledCircuit,
     private backend?: Backend,
-  ) {}
+  ) { }
 
   async init(): Promise<void> {
     // If these are available, then we are in the
@@ -29,9 +29,9 @@ export class Noir {
   }
 
   // Initial inputs to your program
-  async execute(inputs: InputMap): Promise<{ witness: Uint8Array; returnValue: InputValue }> {
+  async execute(inputs: InputMap, foreignCallHandler?: ForeignCallHandler): Promise<{ witness: Uint8Array; returnValue: InputValue }> {
     await this.init();
-    const witness = await generateWitness(this.circuit, inputs);
+    const witness = await generateWitness(this.circuit, inputs, foreignCallHandler);
     const { return_value: returnValue } = abiDecode(this.circuit.abi, witness);
     return { witness: compressWitness(witness), returnValue };
   }
diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts
index f96cddb0eca..982530fb233 100644
--- a/tooling/noir_js/src/witness_generation.ts
+++ b/tooling/noir_js/src/witness_generation.ts
@@ -1,19 +1,21 @@
 import { abiEncode, InputMap } from '@noir-lang/noirc_abi';
 import { base64Decode } from './base64_decode.js';
-import { executeCircuit, WitnessMap } from '@noir-lang/acvm_js';
+import { executeCircuit, WitnessMap, ForeignCallHandler, ForeignCallInput } from '@noir-lang/acvm_js';
 import { CompiledCircuit } from '@noir-lang/types';
 
+const defaultForeignCallHandler: ForeignCallHandler = (name: string, args: ForeignCallInput[]) => {
+  throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`)
+}
+
 // Generates the witnesses needed to feed into the chosen proving system
-export async function generateWitness(compiledProgram: CompiledCircuit, inputs: InputMap): Promise<WitnessMap> {
+export async function generateWitness(compiledProgram: CompiledCircuit, inputs: InputMap, foreignCallHandler: ForeignCallHandler = defaultForeignCallHandler): Promise<WitnessMap> {
   // Throws on ABI encoding error
   const witnessMap = abiEncode(compiledProgram.abi, inputs);
 
   // Execute the circuit to generate the rest of the witnesses and serialize
   // them into a Uint8Array.
   try {
-    const solvedWitness = await executeCircuit(base64Decode(compiledProgram.bytecode), witnessMap, () => {
-      throw Error('unexpected oracle during execution');
-    });
+    const solvedWitness = await executeCircuit(base64Decode(compiledProgram.bytecode), witnessMap, foreignCallHandler);
     return solvedWitness;
   } catch (err) {
     throw new Error(`Circuit execution failed: ${err}`);

From 489c4fb8bd29fee8443844a7f328e5800b51c251 Mon Sep 17 00:00:00 2001
From: TomAFrench <tom@tomfren.ch>
Date: Wed, 25 Oct 2023 17:31:34 +0000
Subject: [PATCH 2/5] chore: linter

---
 tooling/noir_js/src/program.ts            |  7 +++++--
 tooling/noir_js/src/witness_generation.ts | 10 +++++++---
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts
index f09fdb34253..cfd7a715dfe 100644
--- a/tooling/noir_js/src/program.ts
+++ b/tooling/noir_js/src/program.ts
@@ -8,7 +8,7 @@ export class Noir {
   constructor(
     private circuit: CompiledCircuit,
     private backend?: Backend,
-  ) { }
+  ) {}
 
   async init(): Promise<void> {
     // If these are available, then we are in the
@@ -29,7 +29,10 @@ export class Noir {
   }
 
   // Initial inputs to your program
-  async execute(inputs: InputMap, foreignCallHandler?: ForeignCallHandler): Promise<{ witness: Uint8Array; returnValue: InputValue }> {
+  async execute(
+    inputs: InputMap,
+    foreignCallHandler?: ForeignCallHandler,
+  ): Promise<{ witness: Uint8Array; returnValue: InputValue }> {
     await this.init();
     const witness = await generateWitness(this.circuit, inputs, foreignCallHandler);
     const { return_value: returnValue } = abiDecode(this.circuit.abi, witness);
diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts
index 982530fb233..e3ddb1a2a21 100644
--- a/tooling/noir_js/src/witness_generation.ts
+++ b/tooling/noir_js/src/witness_generation.ts
@@ -4,11 +4,15 @@ import { executeCircuit, WitnessMap, ForeignCallHandler, ForeignCallInput } from
 import { CompiledCircuit } from '@noir-lang/types';
 
 const defaultForeignCallHandler: ForeignCallHandler = (name: string, args: ForeignCallInput[]) => {
-  throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`)
-}
+  throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`);
+};
 
 // Generates the witnesses needed to feed into the chosen proving system
-export async function generateWitness(compiledProgram: CompiledCircuit, inputs: InputMap, foreignCallHandler: ForeignCallHandler = defaultForeignCallHandler): Promise<WitnessMap> {
+export async function generateWitness(
+  compiledProgram: CompiledCircuit,
+  inputs: InputMap,
+  foreignCallHandler: ForeignCallHandler = defaultForeignCallHandler,
+): Promise<WitnessMap> {
   // Throws on ABI encoding error
   const witnessMap = abiEncode(compiledProgram.abi, inputs);
 

From 71e0564afef8a74834e3101ed02a40c402212d6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= <github@zepedro.me>
Date: Sat, 28 Oct 2023 12:07:04 +0100
Subject: [PATCH 3/5] chore(docs): adding doc

---
 docs/docs/noir_js/reference/01_noirjs.md | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/docs/docs/noir_js/reference/01_noirjs.md b/docs/docs/noir_js/reference/01_noirjs.md
index d9e5a0c6115..16754f1d096 100644
--- a/docs/docs/noir_js/reference/01_noirjs.md
+++ b/docs/docs/noir_js/reference/01_noirjs.md
@@ -58,10 +58,12 @@ await noirInstance.init();
 
 This async method allows to execute a circuit to get its witness and return value. [`generateFinalProof`](#generatefinalproof) calls it for you, but you can call it directly (i.e. to feed directly to a backend, or to get the return value).
 
+You can optionally provide a foreignCallHandler, to handle functions that should run outside of the prover (i.e. println)
+
 ### Syntax
 
 ```js
-async execute(inputs)
+async execute(inputs, foreignCallHandler)
 ```
 
 ### Parameters
@@ -69,6 +71,7 @@ async execute(inputs)
 | Parameter | Type   | Description                                      |
 | --------- | ------ | ------------------------------------------------ |
 | `inputs`   | Object | An object containing the inputs to your circuit. |
+| `foreignCallHandler` (optional) | Function | A function handling the foreign call from your circuit |
 
 ### Returns
 
@@ -81,6 +84,7 @@ async execute(inputs)
 
 ```js
 const { witness, returnValue } = await noir.execute(inputs)
+const { witness, returnValue } = await noir.execute(inputs, (event) => console.log(event))
 ```
 
 ## `generateFinalProof`

From 499bac1bad94a6b84ed25ed5915f4ee21c46b8e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= <jose@aztecprotocol.com>
Date: Mon, 30 Oct 2023 16:58:19 +0000
Subject: [PATCH 4/5] Update docs/docs/noir_js/reference/01_noirjs.md

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
---
 docs/docs/noir_js/reference/01_noirjs.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/docs/noir_js/reference/01_noirjs.md b/docs/docs/noir_js/reference/01_noirjs.md
index 16754f1d096..7051d3c7778 100644
--- a/docs/docs/noir_js/reference/01_noirjs.md
+++ b/docs/docs/noir_js/reference/01_noirjs.md
@@ -84,7 +84,7 @@ async execute(inputs, foreignCallHandler)
 
 ```js
 const { witness, returnValue } = await noir.execute(inputs)
-const { witness, returnValue } = await noir.execute(inputs, (event) => console.log(event))
+const { witness, returnValue } = await noir.execute(inputs, (name, args) => console.log(`Received foreign call ${name} with arguments ${args}`))
 ```
 
 ## `generateFinalProof`

From 54f852d5c762b804ec1aa530aea7a4b0ee125532 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= <jose@aztecprotocol.com>
Date: Mon, 30 Oct 2023 16:58:39 +0000
Subject: [PATCH 5/5] Update docs/docs/noir_js/reference/01_noirjs.md

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
---
 docs/docs/noir_js/reference/01_noirjs.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/docs/noir_js/reference/01_noirjs.md b/docs/docs/noir_js/reference/01_noirjs.md
index 7051d3c7778..0d6d5abbbff 100644
--- a/docs/docs/noir_js/reference/01_noirjs.md
+++ b/docs/docs/noir_js/reference/01_noirjs.md
@@ -58,7 +58,7 @@ await noirInstance.init();
 
 This async method allows to execute a circuit to get its witness and return value. [`generateFinalProof`](#generatefinalproof) calls it for you, but you can call it directly (i.e. to feed directly to a backend, or to get the return value).
 
-You can optionally provide a foreignCallHandler, to handle functions that should run outside of the prover (i.e. println)
+You can optionally provide a foreignCallHandler, to handle functions that should run outside of the prover (e.g. `std::println`)
 
 ### Syntax