From d6a16d0fc092265fca3250f46c79eb898affc8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Tue, 16 Jan 2024 20:02:43 +0000 Subject: [PATCH] chore(docs): documenting reference, how-to and explainer on the usage of oracles (#4002) # Description This PR adds some more in-depth documentation on oracles, what they are and how to use them. ## Problem\* Closes #3971 Oracles can now be resolved with JSON RPC calls, which is a powerful feature for developers. This PR attempts to provide some information on how they can be part of a development flow ## Summary\* - [ ] Adds the nargo commands for oracles - [ ] Adds an explainer on what are oracles and what can you do with them - [ ] Adds a how-to guide on using oracles - [ ] Adds a tutorial on a small project using oracles --------- Co-authored-by: Savio <72797635+Savio-Sou@users.noreply.github.com> Co-authored-by: josh crites --- cspell.json | 4 +- docs/docs/explainers/explainer-oracle.md | 57 ++++ docs/docs/how_to/how-to-oracles.md | 280 ++++++++++++++++++ docs/docs/noir/concepts/comments.md | 2 +- docs/docs/noir/concepts/data_bus.md | 2 +- .../concepts/data_types/function_types.md | 2 +- docs/docs/noir/concepts/distinct.md | 2 +- docs/docs/noir/concepts/generics.md | 2 +- docs/docs/noir/concepts/lambdas.md | 2 +- docs/docs/noir/concepts/mutability.md | 2 +- docs/docs/noir/concepts/oracles.md | 23 ++ docs/docs/noir/concepts/shadowing.md | 2 +- docs/docs/noir/concepts/traits.md | 1 + .../NoirJS/backend_barretenberg/index.md | 9 +- .../type-aliases/ProofData.md | 2 +- .../NoirJS/noir_js/type-aliases/ProofData.md | 2 +- docs/docs/reference/nargo_commands.md | 3 + docs/package.json | 2 +- docs/static/img/memes/matrix_oracle.jpeg | Bin 0 -> 70206 bytes .../explainers/explainer-oracle.md | 57 ++++ .../version-v0.22.0/how_to/how-to-oracles.md | 280 ++++++++++++++++++ .../noir/syntax/data_types/function_types.md | 2 +- .../noir/syntax/data_types/index.md | 2 +- .../version-v0.22.0/noir/syntax/oracles.md | 23 ++ ...ars.json => version-v0.22.0-sidebars.json} | 0 25 files changed, 745 insertions(+), 18 deletions(-) create mode 100644 docs/docs/explainers/explainer-oracle.md create mode 100644 docs/docs/how_to/how-to-oracles.md create mode 100644 docs/docs/noir/concepts/oracles.md create mode 100644 docs/static/img/memes/matrix_oracle.jpeg create mode 100644 docs/versioned_docs/version-v0.22.0/explainers/explainer-oracle.md create mode 100644 docs/versioned_docs/version-v0.22.0/how_to/how-to-oracles.md create mode 100644 docs/versioned_docs/version-v0.22.0/noir/syntax/oracles.md rename docs/versioned_sidebars/{version-v..-sidebars.json => version-v0.22.0-sidebars.json} (100%) diff --git a/cspell.json b/cspell.json index 6864e863740..0547b956d72 100644 --- a/cspell.json +++ b/cspell.json @@ -172,7 +172,9 @@ "wasi", "wasmer", "Weierstraß", - "zshell" + "zshell", + "nouner", + "devcontainer" ], "ignorePaths": [ "./**/node_modules/**", diff --git a/docs/docs/explainers/explainer-oracle.md b/docs/docs/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/docs/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/docs/how_to/how-to-oracles.md b/docs/docs/how_to/how-to-oracles.md new file mode 100644 index 00000000000..bdb2b1332ba --- /dev/null +++ b/docs/docs/how_to/how-to-oracles.md @@ -0,0 +1,280 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/how_to_oracles/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map(({ inner }) => { + return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: + +```json +{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} +{ "values": [{ "Single": { "inner": "1" }}]} +{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface Value { + inner: string, +} + +interface SingleForeignCallParam { + Single: Value, +} + +interface ArrayForeignCallParam { + Array: Value[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateFinalProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, + ]); + return [oracleReturn.values[0].Array.map((x) => x.inner)]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/docs/noir/concepts/comments.md b/docs/docs/noir/concepts/comments.md index f76ab49094b..b51a85f5c94 100644 --- a/docs/docs/noir/concepts/comments.md +++ b/docs/docs/noir/concepts/comments.md @@ -5,7 +5,7 @@ description: ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments are supported in Noir. keywords: [Noir programming language, comments, single-line comments, multi-line comments] -sidebar_position: 9 +sidebar_position: 10 --- A comment is a line in your codebase which the compiler ignores, however it can be read by diff --git a/docs/docs/noir/concepts/data_bus.md b/docs/docs/noir/concepts/data_bus.md index 6c7e9b60891..e54fc861257 100644 --- a/docs/docs/noir/concepts/data_bus.md +++ b/docs/docs/noir/concepts/data_bus.md @@ -1,6 +1,6 @@ --- title: Data Bus -sidebar_position: 12 +sidebar_position: 13 --- **Disclaimer** this feature is experimental, do not use it! diff --git a/docs/docs/noir/concepts/data_types/function_types.md b/docs/docs/noir/concepts/data_types/function_types.md index e224e860d59..f6121af17e2 100644 --- a/docs/docs/noir/concepts/data_types/function_types.md +++ b/docs/docs/noir/concepts/data_types/function_types.md @@ -23,4 +23,4 @@ fn main() { ``` A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](@site/docs/noir/concepts/lambdas.md) for more details. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/docs/noir/concepts/distinct.md b/docs/docs/noir/concepts/distinct.md index b59e0296b23..6c993b8b5e0 100644 --- a/docs/docs/noir/concepts/distinct.md +++ b/docs/docs/noir/concepts/distinct.md @@ -1,6 +1,6 @@ --- title: Distinct Witnesses -sidebar_position: 10 +sidebar_position: 11 --- The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures diff --git a/docs/docs/noir/concepts/generics.md b/docs/docs/noir/concepts/generics.md index ec2db95839a..ddd42bf1f9b 100644 --- a/docs/docs/noir/concepts/generics.md +++ b/docs/docs/noir/concepts/generics.md @@ -2,7 +2,7 @@ title: Generics description: Learn how to use Generics in Noir keywords: [Noir, Rust, generics, functions, structs] -sidebar_position: 6 +sidebar_position: 7 --- Generics allow you to use the same functions with multiple different concrete data types. You can diff --git a/docs/docs/noir/concepts/lambdas.md b/docs/docs/noir/concepts/lambdas.md index e0a267adfda..be3c7e0b5ca 100644 --- a/docs/docs/noir/concepts/lambdas.md +++ b/docs/docs/noir/concepts/lambdas.md @@ -2,7 +2,7 @@ title: Lambdas description: Learn how to use anonymous functions in Noir programming language. keywords: [Noir programming language, lambda, closure, function, anonymous function] -sidebar_position: 8 +sidebar_position: 9 --- ## Introduction diff --git a/docs/docs/noir/concepts/mutability.md b/docs/docs/noir/concepts/mutability.md index 6abfae3cfa7..9cc10429cb4 100644 --- a/docs/docs/noir/concepts/mutability.md +++ b/docs/docs/noir/concepts/mutability.md @@ -4,7 +4,7 @@ description: Learn about mutable variables, constants, and globals in Noir programming language. Discover how to declare, modify, and use them in your programs. keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] -sidebar_position: 7 +sidebar_position: 8 --- Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned diff --git a/docs/docs/noir/concepts/oracles.md b/docs/docs/noir/concepts/oracles.md new file mode 100644 index 00000000000..2e6a6818d48 --- /dev/null +++ b/docs/docs/noir/concepts/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` diff --git a/docs/docs/noir/concepts/shadowing.md b/docs/docs/noir/concepts/shadowing.md index b5a6b6b38b9..5ce6130d201 100644 --- a/docs/docs/noir/concepts/shadowing.md +++ b/docs/docs/noir/concepts/shadowing.md @@ -1,6 +1,6 @@ --- title: Shadowing -sidebar_position: 11 +sidebar_position: 12 --- Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. diff --git a/docs/docs/noir/concepts/traits.md b/docs/docs/noir/concepts/traits.md index f8a50071a4b..ef1445a5907 100644 --- a/docs/docs/noir/concepts/traits.md +++ b/docs/docs/noir/concepts/traits.md @@ -4,6 +4,7 @@ description: Traits in Noir can be used to abstract out a common interface for functions across several data types. keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 --- ## Overview diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/index.md b/docs/docs/reference/NoirJS/backend_barretenberg/index.md index bfbecb52864..e32501acb71 100644 --- a/docs/docs/reference/NoirJS/backend_barretenberg/index.md +++ b/docs/docs/reference/NoirJS/backend_barretenberg/index.md @@ -24,21 +24,22 @@ ## Functions -### flattenPublicInputs() +### publicInputsToWitnessMap() ```ts -flattenPublicInputs(publicInputs): string[] +publicInputsToWitnessMap(publicInputs, abi): WitnessMap ``` #### Parameters | Parameter | Type | | :------ | :------ | -| `publicInputs` | `WitnessMap` | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | #### Returns -`string`[] +`WitnessMap` *** diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md index 3eb360a78f1..05cebbc4e94 100644 --- a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md @@ -13,7 +13,7 @@ The representation of a proof | Member | Type | Description | | :------ | :------ | :------ | | `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | +| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | *** diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md index 3eb360a78f1..05cebbc4e94 100644 --- a/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md @@ -13,7 +13,7 @@ The representation of a proof | Member | Type | Description | | :------ | :------ | :------ | | `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | +| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | *** diff --git a/docs/docs/reference/nargo_commands.md b/docs/docs/reference/nargo_commands.md index ff3dee8973f..fc2671b2bfc 100644 --- a/docs/docs/reference/nargo_commands.md +++ b/docs/docs/reference/nargo_commands.md @@ -162,6 +162,7 @@ Runs the Noir program and prints its return value. | `--print-acir` | Display the ACIR for compiled circuit | | `--deny-warnings` | Treat all warnings as errors | | `--silence-warnings` | Suppress warnings | +| `--oracle-resolver` | JSON RPC url to solve oracle calls | | `-h, --help` | Print help | _Usage_ @@ -188,6 +189,7 @@ Creates a proof for the program. | `--print-acir` | Display the ACIR for compiled circuit | | `--deny-warnings` | Treat all warnings as errors | | `--silence-warnings` | Suppress warnings | +| `--oracle-resolver` | JSON RPC url to solve oracle calls | | `-h, --help` | Print help | ## `nargo verify` @@ -226,6 +228,7 @@ See an example on the [testing page](../getting_started/tooling/testing.md). | `--print-acir` | Display the ACIR for compiled circuit | | `--deny-warnings` | Treat all warnings as errors | | `--silence-warnings` | Suppress warnings | +| `--oracle-resolver` | JSON RPC url to solve oracle calls | | `-h, --help` | Print help | ## `nargo info` diff --git a/docs/package.json b/docs/package.json index c53ce58f727..1e3efcfe3d1 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "scripts": { - "start": "yarn version::stables && docusaurus start", + "start": "docusaurus start", "build": "yarn version::stables && docusaurus build", "version::stables": "ts-node ./scripts/setStable.ts", "serve": "serve build" diff --git a/docs/static/img/memes/matrix_oracle.jpeg b/docs/static/img/memes/matrix_oracle.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..478af092acaec8191e5725ebbc58ca4a60ed14e5 GIT binary patch literal 70206 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 Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.22.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.22.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..61cabe586e6 --- /dev/null +++ b/docs/versioned_docs/version-v0.22.0/how_to/how-to-oracles.md @@ -0,0 +1,280 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/how_to_oracles/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/syntax/unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map(({ inner }) => { + return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: + +```json +{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} +{ "values": [{ "Single": { "inner": "1" }}]} +{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface Value { + inner: string, +} + +interface SingleForeignCallParam { + Single: Value, +} + +interface ArrayForeignCallParam { + Array: Value[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateFinalProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, + ]); + return [oracleReturn.values[0].Array.map((x) => x.inner)]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md index 61e4076adaf..f6121af17e2 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/function_types.md @@ -23,4 +23,4 @@ fn main() { ``` A function type also has an optional capture environment - this is necessary to support closures. -See [Lambdas](@site/docs/noir/syntax/lambdas.md) for more details. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md index 01cd0431a68..f09bca0ee04 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/noir/syntax/generics.md): +Type aliases can also be used with [generics](../generics.md): ```rust type Id = Size; diff --git a/docs/versioned_docs/version-v0.22.0/noir/syntax/oracles.md b/docs/versioned_docs/version-v0.22.0/noir/syntax/oracles.md new file mode 100644 index 00000000000..2e6a6818d48 --- /dev/null +++ b/docs/versioned_docs/version-v0.22.0/noir/syntax/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` diff --git a/docs/versioned_sidebars/version-v..-sidebars.json b/docs/versioned_sidebars/version-v0.22.0-sidebars.json similarity index 100% rename from docs/versioned_sidebars/version-v..-sidebars.json rename to docs/versioned_sidebars/version-v0.22.0-sidebars.json