From 8e7b198523ae48883db84224da3f04971321985c Mon Sep 17 00:00:00 2001
From: James Zaki <james.zaki@proton.me>
Date: Fri, 1 Nov 2024 19:12:36 +0000
Subject: [PATCH] Add base64 example for gate counts

---
 .gitignore                                    |  1 +
 lib_examples/.gitignore                       |  1 +
 lib_examples/Nargo.toml                       |  4 +++
 lib_examples/base64_example/Nargo.toml        |  8 +++++
 lib_examples/base64_example/Prover.toml       |  2 ++
 lib_examples/base64_example/Prover_LONG.toml  |  2 ++
 lib_examples/base64_example/Prover_SHORT.toml |  2 ++
 lib_examples/base64_example/README.md         | 25 +++++++++++++++
 lib_examples/base64_example/src/main.nr       | 32 +++++++++++++++++++
 .../base64_example/src/test_inputs.nr         | 13 ++++++++
 10 files changed, 90 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 lib_examples/.gitignore
 create mode 100644 lib_examples/Nargo.toml
 create mode 100644 lib_examples/base64_example/Nargo.toml
 create mode 100644 lib_examples/base64_example/Prover.toml
 create mode 100644 lib_examples/base64_example/Prover_LONG.toml
 create mode 100644 lib_examples/base64_example/Prover_SHORT.toml
 create mode 100644 lib_examples/base64_example/README.md
 create mode 100644 lib_examples/base64_example/src/main.nr
 create mode 100644 lib_examples/base64_example/src/test_inputs.nr

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..722d5e7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.vscode
diff --git a/lib_examples/.gitignore b/lib_examples/.gitignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/lib_examples/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/lib_examples/Nargo.toml b/lib_examples/Nargo.toml
new file mode 100644
index 0000000..4fe7c20
--- /dev/null
+++ b/lib_examples/Nargo.toml
@@ -0,0 +1,4 @@
+[workspace]
+members = [
+    "base64_example",
+]
diff --git a/lib_examples/base64_example/Nargo.toml b/lib_examples/base64_example/Nargo.toml
new file mode 100644
index 0000000..3fde666
--- /dev/null
+++ b/lib_examples/base64_example/Nargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "base64_example"
+type = "bin"
+authors = [""]
+compiler_version = ">=0.36.0"
+
+[dependencies]
+base64 = {tag = "v0.3.0", git = "https://github.com/noir-lang/noir_base64.git"}
diff --git a/lib_examples/base64_example/Prover.toml b/lib_examples/base64_example/Prover.toml
new file mode 100644
index 0000000..2a8f242
--- /dev/null
+++ b/lib_examples/base64_example/Prover.toml
@@ -0,0 +1,2 @@
+base64_encoded = ""
+input = ""
diff --git a/lib_examples/base64_example/Prover_LONG.toml b/lib_examples/base64_example/Prover_LONG.toml
new file mode 100644
index 0000000..8b18a71
--- /dev/null
+++ b/lib_examples/base64_example/Prover_LONG.toml
@@ -0,0 +1,2 @@
+input = "The quick brown fox jumps over the lazy dog, while 42 ravens perch atop a rusty mailbox."
+base64_encoded = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZywgd2hpbGUgNDIgcmF2ZW5zIHBlcmNoIGF0b3AgYSBydXN0eSBtYWlsYm94Lg=="
diff --git a/lib_examples/base64_example/Prover_SHORT.toml b/lib_examples/base64_example/Prover_SHORT.toml
new file mode 100644
index 0000000..f8bf6cd
--- /dev/null
+++ b/lib_examples/base64_example/Prover_SHORT.toml
@@ -0,0 +1,2 @@
+input = "The quick br"
+base64_encoded = "VGhlIHF1aWNrIGJy"
diff --git a/lib_examples/base64_example/README.md b/lib_examples/base64_example/README.md
new file mode 100644
index 0000000..8db8c3e
--- /dev/null
+++ b/lib_examples/base64_example/README.md
@@ -0,0 +1,25 @@
+# Base64 example use and bb benchmarking
+
+This makes use of [this](https://github.com/noir-lang/noir_base64.git) base64 library (see Nargo.toml for version)
+
+The lib covers several encode/decode tests, whereas this program has some extra code to facilitate benchmarking the gate counts of a proving backend. Comparisons can be made against other proving backends if desired.
+
+## Test setups for gate counts
+
+Assuming you have `nargo` and a compatible proving backend (eg nargo v0.36.0 and barretenberg bb v0.58.0):
+
+- Choose the desired number of encode/decode runs by setting the corresponding `global` variables in src/main.nr
+- Choose the input strings via the `comptime global` variables (the lengths are managed automatically at compile time)
+- To ensure the test values are expected lengths:
+  - `nargo test`
+- Ensure these test values are in a corresponding Prover toml file eg (`Prover_SHORT.toml`)
+- Execute the program referring to the prover toml file for inputs:
+  - `nargo execute -p Prover_SHORT.toml`
+  - Note there's an optional param that you can use to specify the name of the witness file generated
+  - Optional: `nargo execute -p Prover_SHORT.toml base64_example_SHORT.gz`
+- If using barretenberg, check the gate count referring to the newly created program:
+  - `bb gates -b ../target/base64_example.json`
+  - Note: you can similarly specify a non-default witness file to use with the program
+  - Optional: `bb gates -b ../target/base64_example.json -w ../target/base64_example_SHORT`
+- Repeat this for different runs of encoding and decoding, of different length inputs to collect results
+  - (Automating this is left as an exercise for the reader ;)
\ No newline at end of file
diff --git a/lib_examples/base64_example/src/main.nr b/lib_examples/base64_example/src/main.nr
new file mode 100644
index 0000000..db08f2e
--- /dev/null
+++ b/lib_examples/base64_example/src/main.nr
@@ -0,0 +1,32 @@
+mod test_inputs;
+use base64::{BASE64_ENCODER, BASE64_DECODER};
+
+// Choose number of encode and/or decode runs
+pub global ENCODE_RUNS: u32 = 3;
+pub global DECODE_RUNS: u32 = 0;
+
+// Choose size, and use corresponding Prover.toml during execution
+comptime global TEST_INPUT = test_inputs::TEST_INPUT_SHORT;
+comptime global TEST_BASE64_ENCODED = test_inputs::TEST_BASE64_ENCODED_SHORT;
+
+comptime global U: u32 = comptime { TEST_INPUT.as_bytes().len() };
+comptime global B: u32 = comptime {
+    let mut q = U / 3;
+    let r = U - q * 3;
+    if (r > 0) { q += 1; }; // round up since encoded base64 gets padded
+    q * 4
+};
+
+fn main(input: str<U>, base64_encoded: str<B>) {
+    for _ in 0..ENCODE_RUNS {
+        let _encoded: [u8; B] = BASE64_ENCODER.encode(input.as_bytes());
+    }
+    for _ in 0..DECODE_RUNS {
+        let _decoded: [u8; U] = BASE64_DECODER.decode(base64_encoded.as_bytes());
+    }
+}
+
+#[test]
+fn test() {
+    main(TEST_INPUT, TEST_BASE64_ENCODED);
+}
diff --git a/lib_examples/base64_example/src/test_inputs.nr b/lib_examples/base64_example/src/test_inputs.nr
new file mode 100644
index 0000000..b98a7c9
--- /dev/null
+++ b/lib_examples/base64_example/src/test_inputs.nr
@@ -0,0 +1,13 @@
+//SHORT
+pub comptime global TEST_INPUT_SHORT = "The quick br";
+pub comptime global TEST_BASE64_ENCODED_SHORT = "VGhlIHF1aWNrIGJy";
+
+//LONG
+pub comptime global TEST_INPUT_LONG =
+    "The quick brown fox jumps over the lazy dog, while 42 ravens perch atop a rusty mailbox.";
+pub comptime global TEST_BASE64_ENCODED_LONG = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZywgd2hpbGUgNDIgcmF2ZW5zIHBlcmNoIGF0b3AgYSBydXN0eSBtYWlsYm94Lg==";
+
+//LONG LONG
+// pub comptime global TEST_INPUT_LONG_LONG =
+//     "The quick brown fox jumps over the lazy dog, while 42 ravens perch atop a rusty mailbox.";
+// pub comptime global TEST_BASE64_ENCODED_LONG_LONG = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZywgd2hpbGUgNDIgcmF2ZW5zIHBlcmNoIGF0b3AgYSBydXN0eSBtYWlsYm94Lg==";