|
| 1 | +# Coding for Execution vs Proving |
| 2 | + |
| 3 | +In this intro example you will: |
| 4 | + |
| 5 | +- Create an Aztec contract from scratch |
| 6 | +- Add Aztec dependencies and macros |
| 7 | +- Appreciate different function types/considerations |
| 8 | +- Measure proving cost |
| 9 | +- Run a local node, deploy/interact with contract |
| 10 | + |
| 11 | +## Self Setup |
| 12 | + |
| 13 | +The steps in this section explain how to recreate a project like this from scratch. |
| 14 | + |
| 15 | +### Create project files and first contract |
| 16 | + |
| 17 | +The flow with Noir is much like that of Rust. |
| 18 | + |
| 19 | +```bash |
| 20 | +# Create project dir and boilerplate files |
| 21 | +aztec-nargo new --contract hello |
| 22 | +``` |
| 23 | + |
| 24 | +```bash |
| 25 | +# Add Aztec dependency to `hello/Nargo.toml` |
| 26 | +cd hello |
| 27 | +echo 'aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v0.87.8", directory = "noir-projects/aztec-nr/aztec" }' >> Nargo.toml |
| 28 | +``` |
| 29 | + |
| 30 | +```bash |
| 31 | +# Replace src/main.nr with empty Aztec contract |
| 32 | +echo 'use dep::aztec::macros::aztec; // import aztec macro for use |
| 33 | +
|
| 34 | +#[aztec] // use macro for contract |
| 35 | +pub contract Hello { |
| 36 | + // imports, storage struct, and functions go here |
| 37 | +}' > src/main.nr |
| 38 | +``` |
| 39 | + |
| 40 | +### Add a private function |
| 41 | + |
| 42 | +Inside the empty contract, add the following functions and their requisite macro imports: |
| 43 | + |
| 44 | +```rust |
| 45 | + // ... |
| 46 | + // import function types |
| 47 | + use dep::aztec::macros::functions::{private, public}; |
| 48 | + |
| 49 | + #[private] // use macro to wrap for private execution |
| 50 | + fn mul_8_prv(num: u32) -> u32 { |
| 51 | + num * 8 // more efficient for proving |
| 52 | + } |
| 53 | + |
| 54 | + #[public] // use macro to wrap for public execution |
| 55 | + fn mul_8_exe(num: u32) -> u32 { |
| 56 | + num << 3 // more efficient for execution |
| 57 | + } |
| 58 | + |
| 59 | +// ... |
| 60 | +``` |
| 61 | + |
| 62 | +## Understanding performance |
| 63 | + |
| 64 | +Since private functions are executed client side and the proof of execution is used to advance private state, the size of the circuit is important. The size of a circuit is measured in gates. |
| 65 | + |
| 66 | +Public functions are executed as part of the protocol, so the total cost of operations is important, which is measured in gas. |
| 67 | + |
| 68 | +We can compile and then calculate the gates required for this private function. |
| 69 | + |
| 70 | +## Building the project |
| 71 | +### Compile the contract |
| 72 | + |
| 73 | +For simplicity this project uses make, where `make build` calls `aztec-nargo compile`. Build is the default make target so for convenience simply compile the contract with: |
| 74 | + |
| 75 | +```bash |
| 76 | +# From directory with Markefile & Nargo.toml |
| 77 | +make |
| 78 | +``` |
| 79 | + |
| 80 | +### Showing gate counts in a flamegraph |
| 81 | + |
| 82 | +The gate flamegraph of a specific function can be calculate and presented by passing the function name to: |
| 83 | + |
| 84 | +```bash |
| 85 | +make gate-flamegraph <function-name> |
| 86 | +``` |
| 87 | + |
| 88 | +eg: `make gate-flamegraph mul_8_prv` |
| 89 | + |
| 90 | +Go to the URL in the command output to see the gate count total, and of each sub-section. The exported .svg file is in the `target` directory. |
| 91 | + |
| 92 | +## Using the project |
| 93 | +### Deploy contract to Aztec dev node |
| 94 | + |
| 95 | +First we'll run a local dev environment, aka "sandbox", which includes: |
| 96 | + |
| 97 | +- an Aztec dev node |
| 98 | +- a Private eXecution Environment (PXE) |
| 99 | + |
| 100 | +Both can be started together in a terminal with: `aztec start --sandbox` |
| 101 | + |
| 102 | +We will now use the `aztec-wallet` to interact with them. |
| 103 | + |
| 104 | +```bash |
| 105 | +# Register test account contract addresses from sandbox, into the pxe |
| 106 | +aztec-wallet import-test-accounts |
| 107 | +aztec-wallet get-alias accounts # show account contract aliases -> addresses |
| 108 | +``` |
| 109 | + |
| 110 | +Use the test account aliased to, `test0`, to deploy the compiled contract: |
| 111 | + |
| 112 | +```bash |
| 113 | +aztec-wallet deploy --no-init target/hello-Hello.json --from test0 --alias hello |
| 114 | +``` |
| 115 | + |
| 116 | +Note: |
| 117 | + |
| 118 | +- `no-init` is specified because we do not have or need a constractor/`initializer` for this example |
| 119 | +- The last param requests the deployed contract address be aliased to `hello` |
| 120 | + |
| 121 | +### Command summary script |
| 122 | + |
| 123 | +For convenience/reference, these commands are consolidated in a script. To see them: |
| 124 | +```bash |
| 125 | +./run.sh --help |
| 126 | +``` |
| 127 | + |
| 128 | +### Profile gate count |
| 129 | + |
| 130 | +To see a breakdown of proving times and gate counts per inner-circuit: |
| 131 | + |
| 132 | +```bash |
| 133 | +./run.sh gate-profile mul_8_prv 8 |
| 134 | +``` |
| 135 | + |
| 136 | +This command expects the contract in `hello.nr` to be deployed, and the contract address aliased to `hello`. |
| 137 | + |
| 138 | +This uses the deployed contract to provide a breakdown of time and gates for each inner function. This will become useful when comparing |
| 139 | + |
| 140 | +## Compare implementations |
| 141 | + |
| 142 | + |
| 143 | + |
| 144 | +## Calling private functions |
| 145 | + |
| 146 | + |
| 147 | + |
| 148 | +## Further reading |
| 149 | + |
| 150 | +- For more about optimisation, see [Thinking in Circuits](https://noir-lang.org/docs/explainers/explainer-writing-noir), and [aztec-examples](). |
| 151 | +- To see a side-by-side comparison with Rust, see [noir_by_example](https://github.com/noir-lang/noir-examples/tree/master/noir_by_example#readme). |
0 commit comments