From a98d50e33b885792119a1327de0aa68fdf809026 Mon Sep 17 00:00:00 2001 From: RECTOR Date: Sat, 17 Jan 2026 09:05:12 +0700 Subject: [PATCH] chore: add .gitignore for Noir build artifacts --- .gitignore | 2 ++ funding_proof/target/funding_proof.json | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .gitignore delete mode 100644 funding_proof/target/funding_proof.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1619325 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +funding_proof/target/ +funding_proof/Prover.toml diff --git a/funding_proof/target/funding_proof.json b/funding_proof/target/funding_proof.json deleted file mode 100644 index 4c4f615..0000000 --- a/funding_proof/target/funding_proof.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663","hash":"10749564411501217990","abi":{"parameters":[{"name":"commitment_hash","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"public"},{"name":"minimum_required","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"asset_id","type":{"kind":"field"},"visibility":"public"},{"name":"balance","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"blinding","type":{"kind":"field"},"visibility":"private"}],"return_type":null,"error_types":{"2900908756532713827":{"error_kind":"string","string":"Insufficient balance"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"15835548349546956319":{"error_kind":"string","string":"Field failed to decompose into specified 32 limbs"},"17719928407928969950":{"error_kind":"string","string":"Commitment hash mismatch"}}},"bytecode":"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","debug_symbols":"pdrdThRZF4Dhe+ljDvb62euHW5lMDCozISFoUL/ki+Hep4reL+Ik3WGak6nlaL1uFv3QpfLz8Pn244+/P9w9/PXl2+H6j5+Hj4939/d3f3+4//Lp5vvdl4ft//48jP0/EodrvTpIHi91uLbt0odrvzro9iv86enqwG0fvj/e3u53veps9a83j7cP3w/XDz/u768O/7u5//H8i759vXl4vn6/edx+dlwdbh8+b9ct+Nfd/e0+PV39unucvrWGrptL4+V2yd/ul9P3h/u6P6Zdcn8J91dddD8ffI6Tv/+Zj78j1/3d/nL/fPP+RJQFilhdVAhWIDrkVCFPF1SrVkHt9WexfyvUmUIpn0atKacKfbrgInMVXGZdUlDjU+Ga87KCvLeg9obCuU32aDbZ223/vWAyeEnb9pK6qODyUuh8Z0HHOFU496q2yR7Ex0lZcuYQUs7LWirHycSZz+fUly8PU/uVjPotoWc+kMgX4JFepxJnTxHKK3uGzXcn3C5LZL0k+rLETL5MbONlH0iNl0SNk5+Rs6+LDpBKl516XWi+/3VR735dnD3F214Xb06cfl2cT7zpdXE28bbXxdnE+18XKsEnVSXjki8525f/l4T6yYTFuS98v97OLeOSL51efE5lDrvkkWKOXwWdlxRen+FfhT+3H918unv8/ZHXfPvZq4PN4yWOlzxetmdf2X43630pVwcfxx+7rB/rdt126rZ/6rarr+tc11jXXNda1z5e51hXWVdd19WbqzdXb67eXL25enP1YvVi9WL1YvVi9WL1YvVi9WL1YvVy9XL1cvVy9XL1cvVy9XLvbfvJWtc+XmvvbVxK1lXX1dbV13WuXx/runpV6+f7eO3V69Xr1evV69Xr1evV69Xrdb5e59ueYI43yBAGZTAGZ5gMwZAMxUBZBoMwKIMxUBbKQlkoC2VZOxDlzMqZlTMrZXWGyRAMyUBZKRtlo2yUjW0YZzbObJzZKFsxsA1nG842nLJTdspO2Sk723DO7Jx5cuZJebLnyTYm25hsY1KelCflSTkoB9sIzhycOThzUA72HGwj2EawjaSclJNyUk7KyTaSMydnTs6MNyn2XGyj2EaxDdBJUS7KRRl4gjyBnmBPwCdNudkz/gSAgkBpyr3KikHFoGJQMagYVAwqBnWsso5iWNtQDCoGVSgLZQwqBhWDikHFoGJQMahKWZXBGJxhMlBWyhhUDCoGFYOKQcWgYlCNsgUD28CgYlCdslPGoGJQMagYVAwqBhWD6pQne8agYlAxqJPypIxBxaBiUDGoGFQMKgY1KAd7xqBiUDGoQTkoY1AxqBhUDCoGFYOKQeUdT3nLUwwqBhWDytue8r6nGFQMKgYVg4pBxaBiUJtys2cMKgYVg9qUmzIGFYOGQcOgYdAwaBi0sco2giEZimFtw4SyUMagYdAwaBg0DBoGDYMmlHUwCIMyGANlpYxBw6Bh0DBoGDQMGgbNKJszsA0MGgbNKBtlDBoGDYOGQcOgYdAwaE7Z2TMGDYOGQZuUJ2UMGgYNg4ZBw6Bh0DBoQTnYMwYNg4ZBC8pBGYOGQcOgYdAwaBg0DFpSTvaMQcOgYdB48DSePA2DhkHDoGHQMGgYNAxaUW72jEHDoGHQeAy1poxBw6Bh0DDoGHQMOgZ9rLIPZ5gMwZAMxV2UMegYdAw6Bh2DjkHHoAtlKYa1DcegY9B5FnWljEHHoGPQMegYdAw6Bt0omzKwDQw6Bp1nUTfKGHQMOgYdg45Bx6Bj0J2ys2cMOgYdg86zqE/KGHQMOgYdg45Bx6Bj0CflYM8YdAw6Bp1nUQ/KGHQMOgYdg45Bx6Bj0JNysmcMOgYdg86zqGPQeR903gcdg86zqBdl/gToGHQMOgad90F/Nrj/MfzZYO+DMhiDM0yGYEiGYujjMJ8NPg/CoAzG4AyTIRiSoRgoC2WhLJSFslAWykJZKAtloayUlbJSVspKeTdoz3/zEAzJsP/Dn+5Dr2E3eByEQRls3bUbPA6Ud4PHX5MMlI2yU3bKTtkpO2Wn7JzZObNTdsqT8qQ8Ke8Gj4MzTAbOPCnvBo9Dr2E3eByEgXJQDspBOSgH2wjOHJw5OXNS3g0eB7aRbCPZRlJOykk5KRflYhvFmYszF2cuysWei20U2yi20ZSbclNuyk252UZz5ubMzZl7lWMMBmFQBmNY5RiTIRiSoRjWNkIGgzAoA2VxhskQDMlAWSgrZaWslNUYOLNyZuXMGAwtBrZhbMPYBgbDKBtlo4zBwGBgMDAYGAyn7OwZg4HBwGA4ZaeMwcBgYDAwGBgMDAYGY1Ke7BmDgcHAYATloIzBwGBgMDAYGAwMBgYjKCd7xmBgMDAYSTkpYzAwGBgMDAYGA4OBwSjKxZ4xGBgMDEZRLsoYDAwGBgODgcHAYGAwmnKzZwwmBhODOVY5hzE4w2QIhmQohnXmxGAKZVEGY3CGyUBZKGMwMZgYTAwmBhODicHkfTB5H0wMJgYTg8n7YPI+mBhMDCYGE4OJwcRgYjCNsrNnDCYGE4PplJ0yBhODicHEYGIwMZgYzEl5smcMJgYTgzkpT8oYTAwmBhODicHEYGIwg3KwZwwmBhODmZSTMgYTg4nBxGBiMDGYGMyiXOwZg4nBxGAW5aKMwcRgYjAxmBhMDCYGsyk3e8ZgYjAxWGOVawiDMhiDM0yGYEiGYqAsg0EYlMEYKAtlDBYGC4OFwcJgYbAwWEpZnWEyBEMyUOZZtDBYGCwMFgYLg4XBwmAZZSsGtoHBwmDxLFpOGYOFwcJgYbAwWBgsDNakPNkzBguDhcHiWbQmZQwWBguDhcHCYGGwMFhBOdgzBguDhcHiWbSSMgYLg4XBwmBhsDBYGKykXOwZg4XBwmDxLFpFGYOFwcJgYbAwWBgsDFZTbvaMwcJgYbB4Fq1e5cZgY7Ax2BhsDDYGG4M9VrlHMaxtNAYbg82zaAtlDDYGG4ONwcZgY7Ax2EpZlcEYnGEyUMZg8z7YvA82Bptn0TbK/HmwMdgYbAw274P9bND3YS/n/u+2+7eZjn0QBmUwBmeYDMGQDMXQa5iUJ+VJeVKelCflSXlSnpQn5aAclINyUA7KQTkoB+WgHJSTcj6Xn/Zvf3i8u/l4f/vtcP1z/x6HHw+f+IaG7Yff//+Vn+G7fL8+fvl0+/nH4+3+zQ+vvtV3++8f29+haP/5tH+DxD8=","file_map":{"17":{"source":"use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size::<128>();\n rhi.assert_max_bit_size::<128>();\n }\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Safety: decomposition is properly checked below\n unsafe {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size::<128>();\n xhi.assert_max_bit_size::<128>();\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{assert_gt, decompose, gt, lt, lte_hint, PHI, PLO, TWO_POW_128};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n\n #[test]\n fn check_decompose_edge_cases() {\n assert_eq(decompose(0), (0, 0));\n assert_eq(decompose(TWO_POW_128 - 1), (TWO_POW_128 - 1, 0));\n assert_eq(decompose(TWO_POW_128 + 1), (1, 1));\n assert_eq(decompose(TWO_POW_128 * 2), (0, 2));\n assert_eq(decompose(TWO_POW_128 * 2 + 0x1234567890), (0x1234567890, 2));\n }\n\n #[test]\n fn check_decompose_large_values() {\n let large_field = 0xffffffffffffffff;\n let (lo, hi) = decompose(large_field);\n assert_eq(large_field, lo + TWO_POW_128 * hi);\n\n let large_value = large_field - TWO_POW_128;\n let (lo2, hi2) = decompose(large_value);\n assert_eq(large_value, lo2 + TWO_POW_128 * hi2);\n }\n\n #[test]\n fn check_lt_comprehensive() {\n assert(lt(0, 1));\n assert(!lt(1, 0));\n assert(!lt(0, 0));\n assert(!lt(42, 42));\n\n assert(lt(TWO_POW_128 - 1, TWO_POW_128));\n assert(!lt(TWO_POW_128, TWO_POW_128 - 1));\n }\n}\n","path":"std/field/bn254.nr"},"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\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: [u1; 32] = exponent.to_le_bits();\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 `elem` {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 /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\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 if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 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\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"50":{"source":"/// Funding Proof Circuit\n///\n/// Proves that a user has sufficient balance to cover a transaction\n/// without revealing the actual balance.\n///\n/// Public inputs:\n/// - commitment_hash: Hash of the Pedersen commitment to balance\n/// - minimum_required: Minimum balance required\n/// - asset_id: Asset identifier\n///\n/// Private inputs (witness):\n/// - balance: Actual user balance\n/// - blinding: Blinding factor for commitment\n///\n/// Constraints:\n/// 1. balance >= minimum_required\n/// 2. commitment = pedersen([balance, blinding])\n/// 3. commitment_hash = hash(commitment, asset_id)\n\nuse std::hash::pedersen_hash;\nuse std::hash::blake3;\n\n/// Main entry point for the funding proof circuit\nfn main(\n // Public inputs\n commitment_hash: pub [u8; 32],\n minimum_required: pub u64,\n asset_id: pub Field,\n\n // Private inputs (witness)\n balance: u64,\n blinding: Field,\n) {\n // Constraint 1: Balance must be at least the minimum required\n assert(balance >= minimum_required, \"Insufficient balance\");\n\n // Constraint 2: Compute the Pedersen commitment to (balance, blinding)\n let balance_field = balance as Field;\n let commitment = pedersen_hash([balance_field, blinding]);\n\n // Constraint 3: Verify the commitment hash matches\n // We hash: commitment || asset_id to bind the commitment to the asset\n let computed_hash = compute_commitment_hash(commitment, asset_id);\n\n // Verify the hashes match byte by byte\n for i in 0..32 {\n assert(computed_hash[i] == commitment_hash[i], \"Commitment hash mismatch\");\n }\n}\n\n/// Compute the commitment hash from commitment and asset_id\n/// Uses BLAKE3 for efficiency (built-in to Noir)\nfn compute_commitment_hash(commitment: Field, asset_id: Field) -> [u8; 32] {\n // Convert commitment to bytes (32 bytes, big-endian)\n let commitment_bytes: [u8; 32] = commitment.to_be_bytes();\n\n // Convert asset_id to bytes (32 bytes, big-endian)\n let asset_bytes: [u8; 32] = asset_id.to_be_bytes();\n\n // Create preimage: commitment || asset_id (64 bytes)\n let mut preimage: [u8; 64] = [0; 64];\n for i in 0..32 {\n preimage[i] = commitment_bytes[i];\n preimage[i + 32] = asset_bytes[i];\n }\n\n // Hash with BLAKE3\n blake3(preimage)\n}\n\n// --- Tests ---\n\n#[test]\nfn test_valid_funding_proof() {\n // Test case: balance = 100, minimum = 50\n let balance: u64 = 100;\n let minimum_required: u64 = 50;\n let blinding = 12345 as Field;\n let asset_id = 1 as Field;\n\n // Compute expected commitment hash\n let balance_field = balance as Field;\n let commitment = pedersen_hash([balance_field, blinding]);\n let commitment_hash = compute_commitment_hash(commitment, asset_id);\n\n // This should pass\n main(commitment_hash, minimum_required, asset_id, balance, blinding);\n}\n\n#[test]\nfn test_exact_balance_passes() {\n // Test case: balance exactly equals minimum\n let balance: u64 = 50;\n let minimum_required: u64 = 50;\n let blinding = 67890 as Field;\n let asset_id = 2 as Field;\n\n let balance_field = balance as Field;\n let commitment = pedersen_hash([balance_field, blinding]);\n let commitment_hash = compute_commitment_hash(commitment, asset_id);\n\n main(commitment_hash, minimum_required, asset_id, balance, blinding);\n}\n\n#[test(should_fail_with = \"Insufficient balance\")]\nfn test_insufficient_balance_fails() {\n // Test case: balance < minimum should fail\n let balance: u64 = 40;\n let minimum_required: u64 = 50;\n let blinding = 11111 as Field;\n let asset_id = 1 as Field;\n\n let balance_field = balance as Field;\n let commitment = pedersen_hash([balance_field, blinding]);\n let commitment_hash = compute_commitment_hash(commitment, asset_id);\n\n main(commitment_hash, minimum_required, asset_id, balance, blinding);\n}\n\n#[test(should_fail_with = \"Commitment hash mismatch\")]\nfn test_wrong_commitment_fails() {\n // Test case: wrong commitment hash should fail\n let balance: u64 = 100;\n let minimum_required: u64 = 50;\n let blinding = 12345 as Field;\n let asset_id = 1 as Field;\n\n // Use a completely wrong commitment hash\n let wrong_hash: [u8; 32] = [0; 32];\n\n main(wrong_hash, minimum_required, asset_id, balance, blinding);\n}\n\n#[test(should_fail_with = \"Commitment hash mismatch\")]\nfn test_wrong_blinding_fails() {\n // Test case: correct balance but wrong blinding should fail\n let balance: u64 = 100;\n let minimum_required: u64 = 50;\n let correct_blinding = 12345 as Field;\n let wrong_blinding = 99999 as Field;\n let asset_id = 1 as Field;\n\n // Compute hash with correct blinding\n let balance_field = balance as Field;\n let commitment = pedersen_hash([balance_field, correct_blinding]);\n let commitment_hash = compute_commitment_hash(commitment, asset_id);\n\n // Try to prove with wrong blinding\n main(commitment_hash, minimum_required, asset_id, balance, wrong_blinding);\n}\n","path":"/Users/rz/local-dev/circuits/funding_proof/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file