From 449170f8e2bc4e1fc7b7c63e6358c7f7411c7659 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 16 Jul 2024 17:59:07 -0400 Subject: [PATCH] added readme and license --- LICENSE | 17 +++++++++++++ README.md | 55 +++++++++++++++++++++++++++++++++++++++++ info.sh | 1 - src/lib.nr | 7 ------ target/noir_base64.json | 1 - 5 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 LICENSE create mode 100644 README.md delete mode 100755 info.sh delete mode 100644 target/noir_base64.json diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2fc48ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +Copyright 2024 Aztec Labs + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..022d27e --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# noir_base64 + +A library to encode ASCII into Base64 and decode Base64 into ASCII + +# Usage + +### `fn base64_encode` +Takees an input byte array of ASCII characters and produces an output byte array of base64-encoded characters. The 6-bit base64 characters are packed into a concatenated byte array (e.g. 4 bytes of ASCII produce 3 bytes of encoded Base64) + +### `fn base64_decode` +Takes an input byte array of packed base64 characters and produces an output byte array of ASCII characters (e.g. 3 input bytes of base64 produces 4 output bytes of ASCII) + +### `fn base64_encode_elements` +Takes an input byte array of ASCII characters and produces an output byte array of base64-encoded characters. Data is not packed i.e. each output array element maps to a 6-bit base64 character + +### `fn base64_decode_elements` +Takes an input byte array of base64 characters and produces an output byte array of ASCII characters. Input data is not packed i.e. each input element maps to a 6-bit base64 character + +### Example usage +(see tests in `lib.nr` for more examples) + +``` +use dep::noir_base64; +fn encode() { + // Raw bh: GxMlgwLiypnVrE2C0Sf4yzhcWTkAhSZ5+WERhKhXtlU= + // Translated directly to ASCII + let input: [u8; 44] = [ + 71, 120, 77, 108, 103, + 119, 76, 105, 121, 112, + 110, 86, 114, 69, 50, + 67, 48, 83, 102, 52, + 121, 122, 104, 99, 87, + 84, 107, 65, 104, 83, + 90, 53, 43, 87, 69, + 82, 104, 75, 104, 88, + 116, 108, 85, 61 + ]; + + // will produce packed byte array of base64 chars: + /* + [ + 27, 19, 37, 131, 2, 226, 202, 153, 213, 172, + 77, 130, 209, 39, 248, 203, 56, 92, 89, 57, + 0, 133, 38, 121, 249, 97, 17, 132, 168, 87, + 182, 85 + ] + */ + let result: [u8; 32] = noir_base64::base64_encode(input); +} +``` + +# Costs + +`base64_encode_elements` will encode an array of 44 ASCII bytes in ~470 gates, plus a ~256 gate cost to initialize an encoding lookup table (the initialization cost is incurred once regardless of the number of decodings) + diff --git a/info.sh b/info.sh deleted file mode 100755 index d434b55..0000000 --- a/info.sh +++ /dev/null @@ -1 +0,0 @@ -nargo compile --force && bb gates -b ./target/noir_base64.json \ No newline at end of file diff --git a/src/lib.nr b/src/lib.nr index 3d8b4be..4a6838b 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -175,13 +175,6 @@ pub fn base64_decode(input: [u8; I base64_decode_elements(result) } -// // to measure, run `info.sh` -// fn main(x: [u8; 44]) { -// for i in 0..1 { -// let r: [u8; 32] = base64_encode(x); -// println(f"{r}"); -// } -// } // ooook so we take ascii and encode as base64, we get an undefined character #[test] diff --git a/target/noir_base64.json b/target/noir_base64.json deleted file mode 100644 index 400c8de..0000000 --- a/target/noir_base64.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"0.31.0+6936a52bb4de2170b6e4c41afd9cf4327d4fbeb1","hash":8917370267516413047,"abi":{"parameters":[{"name":"x","type":{"kind":"array","length":44,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"}],"return_type":null,"error_types":{}},"bytecode":"H4sIAAAAAAAA/+2dd3wjRxXHJVedLffe2yW5NJgnyZZMvVADhBJ6J+c7G0IgJCH0loTeO+R6772k997bHYFAICQQCAQCofzNhxl5Nlk/r+Rd7Zv1vsvu5/M+2t/Yn5nvvp+8ejs7K8dj01s6HovVxKf31Uu5bk/YdBzpMqTLka5AuhLpKqSrkU4gvQDpGqRrkU4iXYd0PdINSDci3YR0M9ItSLci3YZ0O9IdSHci3YV0N9I9SPci3Yd0P9IDSA8iPYT0MNIjSC9E+hikj0X6OKQXIX080icgfaLW9k2/pWOL9WtajGUyk9nUJKRhiUiNT+RGRWZ0YiwHORjNjS5L5dLpyVwmlx2fGM+KccikJ2FqdDw9Jaa3k2x9CZ+bSc6TyTjTkyY5n0fHOWWS8/l0nBmTnIKOc9QkJ9BxjpnkTNFxZk1ypuk4cyY5M3Sc4yY5R+k4l5jkHKPjnDDJmaXjXGqSM0fHucwk5zgZZ/5UbIzzBXScKZOcL6TjTJvkfBEdp9E65MV0nEbrkJfQcRqtQ15Kx2m0DllMx2m0DjmFjtNoHfIyOk6jdcjL6TiN1iGvoOM0Woe8ko7TaB3yKjpOo/MMr6bjNDrPcCoZJxidX3oNHafR+vO1dJxG68/X0XEarT9Po+M0Wn++no7TaP35BjpOo/XnG+k4jdafb6LjNFp/nk7HabT+fDMdp9H68y10nEbrz7fScRqtP99Gx2m0/nw7HafR+vMddJxG6893knGmjNaf76LjNFp/vpuO02j9+R46TqP153vpOI3Wn++j4zRaf76fjtNo/fkBOk6j9ecZdJxG688ldJxG688JOk6j9edSOk6j9ecyOk6j9eckHafR+nOKjtNo/flBOk6j9eeHyDjTRuvPM+k4jdafH6bjNFp/nkXHma7QfBfo/k5iFCcjrdZHqrWH6s2s3ijKBFVgq+JVFYaq6FIFTc5F3+qDWq3HUGsd1DoCdY9e3f+27i2fIkPdb1T38tR9MnUPSt3fUfdO1H0JNeev5tPVXPVpMtQcq5q/VHODat7t9CJjq3kkNUej5j/U3IK6blfXxOp6U13LqeskdQ2i6ntVO6u6VNV8Z8hQH9zqQ1F94KiTuTpRqpOQOqep84X6W1Tv87MKjK02a/063hbrV+Fzs/qL0/YLHBg/QsnI1ag4A8aPRkYJKGPAeHZklIByBowfi4wSUMGA8ZzIKAGVDBjPjYwSUMWA8bzIKAHVDBg/HhklIMGA8fzIKAELGDB+IjJKQA0Dxk9GRgmoZcD4qcgoAUkGjJ+OjBJQx4DxM5FRAuoZMH42MkpAAwPGz0VGCWhkwPj5yCgBTQwYvxAZJaCZAeMXI6MEtDBg/FJklIBWBowXREYJaGPAeGFklIB2BowXRUYJ6GDA+OXIKAGdDBi/EhkloIsB41cjowR0M2D8WmSUgB4GjF+PjBLQy4DxG5FRAvoYMH4zMkpAPwPGb0VGCRhgwPjtyCgBgwwYvxMZJWCIAeN3I6MEDDNg/F5klIARBozfj4wSsJAB4w8iowQcw4Dxh5FRAo5lwPijyCgBxzFg/HFklIBFDBh/Ehkl4HgGjD+NjBJwAgPGn0VGCTiRAePPKRnLkEGLnGAzouRt9vcBgSh1c/rKmlLRHL9VpUS0Al/8URLaOc59lYRW+OsTvKMVecLfM1rRh9A9ohV/Ttob2lyP8npBm/NpUw9oLh6IdI3m5pk9t2juHitzh+byySdXaK4fznGB5v75kbnRvDziMBeap1X4c6B5XCheFO0Cb30VRbvQY1/F0C7y3FdhtJIWLRZAK21dnTNaqUu/nNBKXp3kgOZjAc0sND9rPDCav2UIM9F83imfgeb7Zq4Nzf/9xmfRKG6JWWgkd200GtGNhTwa1dy3QqObns0IwhlE0kmuft3PxTKWy1ghY6WMVTJWy1gjY62MdTLWy9ggY6OMTTI2y9giY6uMbTK2y9ghY6eMXTJ2y9gjY6+MfTL2yzgg46CMQzIuUQPHpy+wyjVDIvasXo70CqRXIr0K6dVIr0F6LdLrkF6P9AakNyK9CenNSG9BeivS25DejvQOpHcivQvp3UjvQXov0vuQ3o/0AaQPIn0I6Uu0tm8V+nWxfhXTfx4lbxyuT/1+n/YvYvSTGgW9UNtRfB3t14sHg/Yivx2d1/t+vfjlvHihtqNvXsKvF7+aNy/y21E1f+LXi4fm1wu1HTXzPH69+PX8e5Hfjob5KL9e/CYkXqiN+7yZXy8eDpEX+Y3x/J5fL34bNi/UxnQe0q8XvwujF/mN33ypXy8eCa0XauM1r+vXi9+H2ov8xmb+2a8Xj4bfC7XNmCf3e8wXE/Q1OaU2AcsJuR4LyAs/x6y8WEHS17SvK/33ldL5g1WEXvwhzF5knuGE1f76ErZjhjV++krNyB+sJfTij+H0QiBOWFdiX2NTs44Z1pfWV84hf7CB0IvHw+ZFzpETNnrvK1vgmGGT176yBfMHmwm9+FN4vEgV4YQtXvrKFj1m2Oq+r6Vz5A+2EXrx5zB4kZ2TE7a760u4OGbY4aYv4Sp/sJPQiyfm14tRl5ywa66+Mq6PGXYX7Ssz5SF/sIfQi7/MlxdZT5ywt3BfOY/HDPsK9DU+5Tl/sJ/Qi78G74UogRMOOPUlSjpmODi7Lygxf3CI0Isng/RiWcmccAkdJxCufYEHCb34W0BeCH8bEK6RAMJ7/PAQoRd/Z+IF4b1gILyXCQ8TevEUEy8I73kB4T0beITQi38w8YJwbh8eJezrMUIv/snEC8I5TCCcg4PHCb14mokXhHM1QDjXAE8QevEvJl4QXpMC4TUVPEnoxb+ZeEFYewNh7QhPEXrxHyZeENYYQPgZCU8TevFfJl4QnkuB8FwAhO9loPSiLDZzo342afZ3HJX+bJLT1/CUiub4TTElolF+mYn1LOKlMi6TcbmMK2RcKeMqGVfLuEbGtTKuk3G9jBtk3CjjJhk3y7hFxq0ybpNxu4w7ZNwp4y4Zd8u4R8a9Mu6Tcb+MB2QclnFEDWx7FlEx2J9luwzpy5G+Aukrkb4K6auRvgbpa5G+Dunrkb4B6RuRvgnpm5G+Belbkb4N6duRvgPpO5G+C+m7kb4H6XuRvg/p+5F+AOnDSB+JmX8WkcPfu9/PwvZ4wJ+FBOclv8d8KUFf1tqvywi5OgLywu/ar8tJ+spjwhX++3pm7deVhF50htkL29qvq/z1NWPt19V++kJrv64h9KIrnF7MWvt1bYl9Oa39uq60vhzXfl1P6EV32LwosPbrBu99FVz7daPXvoqs/bqJ0Iue8HhRdO3XzV76mmPt1y3u+5pz7dethF70hsELF2u/bnPXl6u1X7e76cvl2q87CL3om18vXK/9unOuvjys/borRrf2625CL/rnywuPa7/uidGt/bo3Rrf26z5CLwaC96KktV/3x+jWfj0Qo1v7dZjQi8EgvfCx9utIjG6ul3CuAezXyn69GAp6DqS0DQivSYHwmgq6Cb0YZuIFYe0NhLUj9BF6McLEC8IaAwg/I2GQ0IuFTLwgPJcC4bkACN/LQOlFpe6nXL/Gbft4oxkzO2Go35ShfpeZy4UAle9B1Df1P4ggXD9v7J9YHGLAeJAB4wEGjPsZMO5jwLiXAeMeBoy7GTDuYsC4kwHjDgaM2xkwbmPAuJUB4xYGjJsZMG5iwLiRAeMGBozrGTCuY8C4lgHjGgaMqxkwrmLAuJIB4woGjMsZMF7MgPEIA8bDBhjzkNbE/Emx2Iz2stj0BLH6uZo8rpJRHZteDL9ARo2MWhlJGXUy6mU0yGiU0SSjWUaLjFYZbTLaZXTI6JTRJaNbRo+MXhl9MtRDHAOx6UnSIRnDMkZkLJRxjIxjZaj/JL9Ihvr/1+pfK58YK7JZDpyrd+yr+AepsplLZapsnS9EDGX2gRPPvqj2uNZx1F6mdRlqL9faeh3U7RVaV6Dfr9S6ErVXaV2F2qu1rkbtCUuj9gVaL0DtNVrXoPZarWtRe1LrJGqv07oOtddrXY/aG7RuQO2NWjei9iatm1B7s9bNqL1F6xbU3qp1K2pv07oNtbdr3Y7aO7TuQO2dWnei9i6tu1B7t9bdqL1H6x7U3qt1L2rv07oPtfdr3Y/aB7QeQO2D1vsVtQ9pPYTah7UeRu0jWo/Y2q2f5fuPUf1NC6H6LafuV57F1QnTOuGW246jkv4YMqrfKkPHUK37snJfa9uvtrVZ+5W2tkr0e+oV9L764FhoP1Hr/Fi/Gyc8DtVvDXl+Mrna2OwnxuJID9r2a2zHuYCcx9RxTv+N1NrYafrNTqhcJVGuEihX9bbfsTMkDeQvbhvX6tvSSYex6XKRSqmx61zkos6Bpy7gXNQ5jE2Xi7H8+6LeRS7qHXjqA85FvcPYhLkYV2M3uMhFgwNPQ8C5aHAYmzAXk2rsRhe5aHTgaQw4F40OYxPmIqPGbnKRiyYHnqaAc2GN55U5GQLmBNqnGTu9RI3d7CIXzQ48zQHnwhrPK3MyBMwJtE8z9lh+7BYXuWhx4GkJOBctDmMT1nH52qXVRS5aHXhaA86FNd5zgbk5BMwJtE8zdjZfF7W5yEWbA09bwLmwxvPKnAwBcwLt04ydWqrGbneRi3YHnvaAc2GN55U5GQLmBNqnGXss71+Hi1x0OPB0BJyLDoexCXMxqsbudJGLTgeezoBzYY3nlbkhBMwJtE8z9lhWjd3lIhddDjxdAeeiy2Fsws/V/HVlt4tcdDvwdAeci26HsQnfFzk1do+LXPQ48PQEnAtrPK/MSYbMTSFgTqB9mrHTaTV2r4tc9Drw9Aaci16HsQlzkb+u7HORiz4Hnr6Ac2GN55W5jSFzkiFzF0Pm1hAwJ9A+zdhZocbud5GLfgee/oBzYY3nlbmDIXOSIXMTQ+Zahswc3xt1DJnrGTI3MGRuZMgcnZ+fO3lOoH2asbP5+coBF7kYcOAZCDgX1nhemRtCwJxA+zRjZ/NzBIMucjHowDMYcC6s8bwy1zNk7mTI3MCQuYMhcyNDZo5/gxzfz10MmTn+DXI8P3PMcwtD5iRD5jaGzGHIcwLt04ydza8jGHKRiyEHnqGAc2GN55W5niFzI0PmLobM3QyZkwyZm0LAnED7NGOn82tuhl3kYtiBZzjgXAw7jE34ebJMjT3iIhcjDjwjAefCGo8js9LWs8rnnHfm2efH0FZl27c/oGw9CG3/euUK28/tD3tbbVYyTnXo0z5O3BbWlkBj/a/A7wyiPuw/OxWNoR5E/j+IP7mqFzIBAA==","debug_symbols":"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","file_map":{"22":{"source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n","path":"std/field.nr"},"30":{"source":"mod hash;\nmod aes128;\nmod array;\nmod slice;\nmod merkle;\nmod schnorr;\nmod ecdsa_secp256k1;\nmod ecdsa_secp256r1;\nmod eddsa;\nmod embedded_curve_ops;\nmod sha256;\nmod sha512;\nmod field;\nmod ec;\nmod unsafe;\nmod collections;\nmod compat;\nmod convert;\nmod option;\nmod string;\nmod test;\nmod cmp;\nmod ops;\nmod default;\nmod prelude;\nmod uint128;\nmod bigint;\nmod runtime;\nmod meta;\n\n// Oracle calls are required to be wrapped in an unconstrained function\n// Thus, the only argument to the `println` oracle is expected to always be an ident\n#[oracle(print)]\nunconstrained fn print_oracle(with_newline: bool, input: T) {}\n\nunconstrained pub fn print(input: T) {\n print_oracle(false, input);\n}\n\nunconstrained pub fn println(input: T) {\n print_oracle(true, input);\n}\n\n#[foreign(recursive_aggregation)]\npub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {}\n\n// Asserts that the given value is known at compile-time.\n// Useful for debugging for-loop bounds.\n#[builtin(assert_constant)]\npub fn assert_constant(x: T) {}\n\n// Asserts that the given value is both true and known at compile-time\n#[builtin(static_assert)]\npub fn static_assert(predicate: bool, message: str) {}\n\n// from_field and as_field are private since they are not valid for every type.\n// `as` should be the default for users to cast between primitive types, and in the future\n// traits can be used to work with generic types.\n#[builtin(from_field)]\nfn from_field(x: Field) -> T {}\n\n#[builtin(as_field)]\nfn as_field(x: T) -> Field {}\n\npub fn wrapping_add(x: T, y: T) -> T {\n crate::from_field(crate::as_field(x) + crate::as_field(y))\n}\n\npub fn wrapping_sub(x: T, y: T) -> T {\n //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow\n crate::from_field(crate::as_field(x) + 340282366920938463463374607431768211456 - crate::as_field(y))\n}\n\npub fn wrapping_mul(x: T, y: T) -> T {\n crate::from_field(crate::as_field(x) * crate::as_field(y))\n}\n\n#[builtin(as_witness)]\npub fn as_witness(x: Field) {}\n\n","path":"std/lib.nr"},"50":{"source":"struct Base64DecodeBE {\n table: [u8; 128]\n}\nimpl Base64DecodeBE {\n fn new() -> Self {\n Base64DecodeBE {\n table: [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0-9\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 10-19\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 20-29\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 30-39\n 0, 0, 0,// 40-42\n 62,// 43\n 0, 0, 0,// 44-46\n 63,// 47\n 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,// 48-57\n 0, 0, 0, 0, 0, 0, 0,// 58-64\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,// 65-90 (A-Z)\n 0, 0, 0, 0, 0, 0,// 91-96\n 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,// 97-122 (a-z)\n 0, 0, 0, 0, 0// 123-127\n ]\n }\n }\n\n fn get(self, idx: Field) -> u8 {\n self.table[idx]\n }\n}\n\nfn base64_decode_elements(input: [u8; InputElements]) -> [u8; InputElements] {\n // for some reason, if the lookup table is not defined in a struct, access costs are expensive and ROM tables aren't being used :/\n let mut BASE64_DECODE_BE = Base64DecodeBE::new();\n\n let mut result: [u8; InputElements] = [0; InputElements];\n\n for i in 0..InputElements {\n result[i] = BASE64_DECODE_BE.get(input[i] as Field);\n }\n result\n}\n\nfn base64_decode(input: [u8; InputElements]) -> [u8; OutputBytes] {\n let decoded: [u8; InputElements] = base64_decode_elements(input);\n // 240 bits fits 40 6-bit chunks and 30 8-bit chunks\n // we pack 40 base64 values into a field element and convert into 30 bytes\n // TODO: once we support arithmetic ops on generics, derive OutputBytes from InputBytes\n let mut result: [u8; OutputBytes] = [0; OutputBytes];\n let BASE64_ELEMENTS_PER_CHUNK: u64 = 40;\n let BYTES_PER_CHUNK: u64 = 30;\n let num_chunks = (InputElements / BASE64_ELEMENTS_PER_CHUNK)\n + (InputElements % BASE64_ELEMENTS_PER_CHUNK != 0) as u64;\n\n for i in 0..num_chunks - 1 {\n let mut slice: Field = 0;\n for j in 0..BASE64_ELEMENTS_PER_CHUNK {\n slice *= 64;\n slice += decoded[i * BASE64_ELEMENTS_PER_CHUNK + j] as Field;\n }\n let slice_bytes: [u8; 30] = slice.to_be_bytes(30).as_array();\n for j in 0..BYTES_PER_CHUNK {\n result[i * BYTES_PER_CHUNK + j] = slice_bytes[j];\n }\n }\n\n let base64_elements_in_final_chunk = InputElements - ((num_chunks - 1) * BASE64_ELEMENTS_PER_CHUNK);\n\n let mut slice: Field = 0;\n for j in 0..base64_elements_in_final_chunk {\n slice *= 64;\n slice += decoded[(num_chunks - 1) * BASE64_ELEMENTS_PER_CHUNK + j] as Field;\n }\n for _ in base64_elements_in_final_chunk..BASE64_ELEMENTS_PER_CHUNK {\n slice *= 64;\n }\n\n // TODO: check is it cheaper to use a constant value in `to_be_bytes` or can we use `bytes_in_final_chunk`?\n let slice_bytes: [u8; 30] = slice.to_be_bytes(30).as_array();\n let num_bytes_in_final_chunk = OutputBytes - ((num_chunks - 1) * BYTES_PER_CHUNK);\n for i in 0..num_bytes_in_final_chunk {\n result[(num_chunks - 1) * BYTES_PER_CHUNK + i] = slice_bytes[i];\n }\n result\n}\n\n// to measure, run `info.sh`\nfn main(x: [u8; 44]) {\n for i in 0..1 {\n let r: [u8; 32] = base64_decode(x);\n println(f\"{r}\");\n }\n}\n\n#[test]\nfn test_bodyhash_base64_decode1() {\n // Raw bh: GxMlgwLiypnVrE2C0Sf4yzhcWTkAhSZ5+WERhKhXtlU=\n // Translated directly to ASCII\n let input: [u8; 44] = [\n 71, 120, 77, 108, 103,\n 119, 76, 105, 121, 112,\n 110, 86, 114, 69, 50,\n 67, 48, 83, 102, 52,\n 121, 122, 104, 99, 87,\n 84, 107, 65, 104, 83,\n 90, 53, 43, 87, 69,\n 82, 104, 75, 104, 88,\n 116, 108, 85, 61\n ];\n let res: [u8; 32] = base64_decode(input);\n println(f\"DECODED = {res}\");\n let expected_res: [u8; 32] = [\n 27, 19, 37, 131, 2, 226, 202, 153, 213, 172,\n 77, 130, 209, 39, 248, 203, 56, 92, 89, 57,\n 0, 133, 38, 121, 249, 97, 17, 132, 168, 87,\n 182, 85\n ];\n assert(res == expected_res);\n}\n","path":"/Users/zac/noir_base64/src/main.nr"}},"names":["main"]} \ No newline at end of file