@aztec/protocol-contracts 0.0.1-commit.2d9cb6034 → 0.0.1-commit.2e20a94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "transpiled": true,
3
- "noir_version": "1.0.0-beta.19+c033e48bb813206dd272c1d24ea3c220f69f3fc4",
3
+ "noir_version": "1.0.0-beta.20+04a373ed8e9cf67ac4f7efea14009f3c3a856d58",
4
4
  "name": "ContractInstanceRegistry",
5
5
  "functions": [
6
6
  {
@@ -31,8 +31,8 @@
31
31
  }
32
32
  }
33
33
  },
34
- "bytecode": "JwACBAEoAAABBIBEJwAABEQnAgIEACcCAwQAHwoAAgADAEMlAAAAPC0CAkMnAgMEQycCBAQBOw4ABAADHgIAAwknAgQBASQCAAMAAABTJQAAAn0eAgADASkCAAQA71JTTScCBQABKwIABgAAAAAAAAAAAwAAAAAAAAAALQgBBycCCAQFAAgBCAEnAwcEAQAiBwIILQoICS0OBAkAIgkCCS0OBQkAIgkCCS0OAwkAIgkCCS0OBgktCAEDJwIEBAUACAEEAScDAwQBACIHAgQAIgMCBT8PAAQABScCBAQBACoDBAUtCwUFJwIDAAAKKgUDBCcCAwEACioEAwYkAgAGAAABCCUAAAKPHgIAAwYeAgAEAC8qAAUABAAGHAoGBQQcCgUEAAIqBgQFLAIABAAtXgmLgro3tDuZoTFhGP0g1C9RZsnp8T+16mWpbR4KbQQqBQQGHAoGBwQcCgcFAAIqBgUHBCoHBAYcCgYIAhwKCAcAHAoHCAIcCggJARwKCQcCHAoHCAEcCgcJAAIqBgkKLAIABgAwM+okblBuiY6X9XDK/9cEywu0YDE/tyCynhOeXBAAAQQqCgYJHAoJCwQcCgsKAAIqCQoLBCoLBAkcCgkLAhwKCwQAHAoECwIcCgsMARwKDAQCHAoECwEcCgQMAAIqCQwNBCoNBgkcCgkMBBwKDAYAHAoGCQUWCgsGHAoECwUcCgYEBQQqCwkGHAoKCQUWCggKHAoHCAUcCgoHBQQqCAkKHAoFCQUMKgMJBSkCAAMFAAFRgCQCAAUAAAJoIwAAAlQEKggKBAQqBwMFACoEBQIjAAACfAQqCwYFBCoEAwYAKgUGAiMAAAJ8JioBAAEFT99KitfP8NM8BAIBJioBAAEFursh14IzGGQ8BAIBJg==",
35
- "debug_symbols": "rZjbbts4EIbfRde+4Jx4yKsUReAkTmHAcALXXmAR+N13xtJQdgFyW6I31u9f1qfhcIaU9TW97V4uP573x/ePn9PTt6/p5bQ/HPY/ng8fr9vz/uOo7tcU7CPqJ22mKNMTb6YU5kO+HTJNT1EP+g30NyXNRwi4CCQXfor8FLnD7rA7Ai5kERbELNhFWUTyW6QlCsgGFBNxEQVcLA4GcOEOuAMWho4KEV24Q/abbCIugt1hd8QdKYuwmBFNqIPmJHUoqLBQyU7ltIhiDpkwR3NMxC70ctIIidmFORoYiTnJhDl6C7KbzsKd5E5yJ7uTzSkqijocTKjDsJnYRnoTNlJGE3ERNlImE+ZohBzNERNxEcmd5E52J7tjs8PRhDk6CrHZ4WzCHA1MbHZmoY5ohIILR1AWh4ILd9gcMCHzSMUydnMsY7NwxzImaMIcvl43k3fD8/m021kz3LWHNs3n9rQ7nqen4+Vw2Ez/bA+X249+fm6Pt+N5e9KzGsju+KZHBb7vDztT1816dWhfqv1TeLkctNZiRcgjA9qMEjEuiBI5rYT8QMBOFCHXICCshASj48itcXQZwitDJLUY0maQldCNoP0xNA6xJcJjYGrFkHoMXhFFKiHLAyG3CZi9pKismUTAB0DplAQFD6EQY0VAKo9V1UlFCdb6MyOU0GZAbzocQfluIPQLoVOaulj7jCLkNMZA8gbRlZ7bDG4zdFny2hTdW9Zs5N8OQ+eyZqMUaIbRKy0ong2gEFulBR1EQnRE0j1tRfBgj6T2mtWpUE2nbTozJHKkViDYiSRz8kAy32X015WvU6GxJjRBc+H7n4HUIFSX1BwIdSAZQ3ZIRmpng3urOIrXuerU3gmkBwlWPQskEDchsZNUyD6aiAGbiE6ZYnICluZC3htIKQnXcXBuBtGZW33qqh0rnTD6MxtrHFmX5dbMUqdI9ZlRajYo3y3F8AeMWDeVcL+A/RFD6vYaQIYYmgKojAiDjNpyBECjDK4MTGMMkFQZMQ4yitcHIYzGkeNfYNScIoUxBq75wDgYB+ZaHwSjcawPUIQ8xiCpvU8RBxl1HSSGYQb+BUbNKeNg3/Latzzat4lqzyUZnJdc13X9VzvY+6U+VHIIpcn4/X1f/762Fnbp7A6oO6wv7IHvG0YZ3/Xr9nV/enhlczXYab99OeyWr++X4+vd2fO/n37GX/l8nj5ed2+X085I63sf+8f9DfSJFYC/X+1+/wE="
34
+ "bytecode": "JwACBAEoAAABBIBEJwAABEQnAgIEACcCAwQAHwoAAgADAEMlAAAAPC0CAkMnAgMEQycCBAQBOw4ABAADHgIAAwknAgQBASQCAAMAAABTJQAAAngeAgADASkCAAQA71JTTScCBQABKwIABgAAAAAAAAAAAwAAAAAAAAAALQgBBycCCAQFAAgBCAEnAwcEAQAiBwIILQoICS0OBAkAIgkCCS0OBQkAIgkCCS0OAwkAIgkCCS0OBgktCAEDJwIEBAUACAEEAScDAwQBACIHAgQAIgMCBT8PAAQABScCBAQBACoDBAUtCwUFJwIDAAAKKgUDBCcCAwEACioEAwYkAgAGAAABCCUAAAKKHgIAAwYeAgAEAC8qAAUABAAGHAoGBQQcCgUEAAIqBgQFLAIABAAtXgmLgro3tDuZoTFhGP0g1C9RZsnp8T+16mWpbR4KbQQqBQQGHAoGBwQcCgcFAAIqBgUHBCoHBAYcCgYIAhwKCAcAHAoHCAIcCggJARwKCQcCJwIIAgAKKgcICRYKCQccCgcKAAIqBgoLLAIABgAwM+okblBuiY6X9XDK/9cEywu0YDE/tyCynhOeXBAAAQQqCwYKHAoKDAQcCgwLAAIqCgsMBCoMBAocCgoMAhwKDAQAHAoEDAIcCgwNARwKDQQCCioECAwWCgwEHAoECAACKgoIDQQqDQYIHAoICgQcCgoGABwKBggFHAoMBgUcCgQKBQQqCggEHAoLCAUcCgkKBRwKBwkFBCoJCAccCgUIBQwqAwgFKQIAAwUAAVGAJAIABQAAAmgjAAACWQQqCgMEACoHBAIjAAACdwQqBgMFACoEBQIjAAACdyYqAQABBU/fSorXz/DTPAQCASYqAQABBbq7IdeCMxhkPAQCASY=",
35
+ "debug_symbols": "rVhbbuM4ELyLvv3BfvGRqwwGgZMoAwOGE3jsBRaB777dtpqyByB3lrM/VrlklYrNYlPW1/Q2v5x/PO8O7x8/p6dvX9PLcbff73487z9et6fdx0HZrynYR9RP2kxRpifeTCncDvl6yDQ9RT3oN9DflHQ7QsAFIDnwU+SnyBl2hp0RcCALMBM3wA7KApLfIi0uIJugGIgLKOBgYTCAA2fAGTAbOipEdOAM2W+ygbgAdoadEWekLMA8IxpQBo1JylBQYFbJTuW0gGIMGTBGa0zEDvRyUofE7MAYNUZiTDJgjN6C7KY34Mz1psVAWUBWhoOBsoDiTLEJhs3EQcvLaMAYNcYsCxDLAhuQBdg0sRgwRo3xNS/JgCwgO5ONUWNcggNj1JiE4ED9SDCgDkX9CBiDBoxRG4LswBi1IVaxG3CGnbGKiToUq9gNOBOdsYqJmhermOTLZTP5sng+HefZVsXdOtHV87k9zofT9HQ47/eb6a/t/nz90c/P7eF6PG2PelbHMR/e9KiC77v9bOiyWa8O7UsB2YZ4vVxxkiohjxrQ1igRYJEokXBVyA8K2HERcnQTEEpVSDA6jtQaR1cjhlUjQmxpSFuDLF1XBV0oQ+PQcKweArY8pH4tqkRZZzTLg0JuK2D2SOl6rdcj4INA6USCglsoxOsgIJXHVHVKUQL7bJRQQlsDetPhEpTvBkK/KHSiqV3bo4mQeUwDyW0gxo4PbmswJJ8TxrDGG/Jv26CSoE5rKk0bvWhB8XwDhdiKFnQkEqJLJN3cVgkeXCPU7lmdhOqGz14NxZFaRrDjJOvGtGhkTrHZ+ToJjbWgCVKrYfzLQJKsAympORDqiGQM2UWyxrUpwr0ujlTbeNBJataj00BLKalqBOCmRuzUVJ/dFo0IuW2jk1JMXg4szT7eH4c9TPg4MDdNdKaWROqCvd8KfrXRn9hYfWTtyq2JpU5G9dlRajUo33Vi+A8adamQzuughtTdNYAMaWgJak1DhEGNuuIIgEY1uGpgGtMASVUjxlGNWDUS/A8aoz5K1UAc9VHCn2vkmjEkHtPQh8eqMVpTzDVjBKM+cs0Y4di6JVozRqMZozUfNFqPB41RH2vG9CFqVCP8ucaaMabB/sFrL+RYxjQS+96gJcUxjXz3X2Gwr+ufDM8YB2j3wt9/DBKA1kYnvV0/1D+AGPjeiGp816/b193x4VXWxcSOu+3Lfl6+vp8Pr3dnT39/+hl/FfZ5/Hid387H2ZTW92H2nugb6L8Z3VK+X+x+/wA="
36
36
  },
37
37
  {
38
38
  "name": "public_dispatch",
@@ -52,10 +52,6 @@
52
52
  ],
53
53
  "return_type": null,
54
54
  "error_types": {
55
- "361444214588792908": {
56
- "error_kind": "string",
57
- "string": "attempt to multiply with overflow"
58
- },
59
55
  "1998584279744703196": {
60
56
  "error_kind": "string",
61
57
  "string": "attempt to subtract with overflow"
@@ -68,7 +64,7 @@
68
64
  "error_kind": "string",
69
65
  "string": "New update delay is too low"
70
66
  },
71
- "9663057235827813545": {
67
+ "11194752367584870169": {
72
68
  "error_kind": "fmtstring",
73
69
  "length": 27,
74
70
  "item_types": [
@@ -99,8 +95,8 @@
99
95
  }
100
96
  }
101
97
  },
102
- "bytecode": "JwACBAEoAAABBIBUJwAABFQlAAAAQScCAwQBJwIEBAAfCgADAAQAUy0IUwIlAAAA8CcCAgRUJwIDBAA7DgADAAIpAABDAPqRAsspAABEAMB7XhkpAABFAAVVe/onAEYAAywAAEcALc/6U80Ocdp7SiJnezNCv8O5BD9Qgb6lg2itAI6qbzcoAABIBQJYLAAASQAwZE5y4TGgKbhQRbaBgVhdKDPoSHm5cJFD4fWT8AAAACcASgQDJwBLBAAnAEwAACcATQEBJwBOBAEnAE8AAScAUAQCJwBRAAIrAABSAAAAAAAAAAADAAAAAAAAAAAmCiICQwMnAgUEACcCBwQDACoFBwYtCAEEAAgBBgEnAwQEAQAiBAIGLQ4FBgAiBgIGLQ4FBicCBgQDACoEBgUnAgUBACkCAAYAA21SfykCAAcA71JTTSkCAAgFAAFRgCQCAAMAAAFbIwAABUktCAEJJwIKBAIACAEKAScDCQQBACIJAgofMABOAE4ACgAiCU4KLQsKCh4CAAkBCiIJSQsWCgsMHAoMDQAEKg0JDAoqCwUJJAIACQAAAbInAg0EADwGDQEeAgAJAC0IAQsnAg0EBAAIAQ0BJwMLBAEAIgsCDS0KDQ4tDgYOACIOAg4tDgkOACIOAg4tDgwOJwINBA4tCAAOLQoLEAAIAA0AJQAAC+otAgAALQoQCTMKAAkACyQCAAsAAAIbJQAADZstCAEJJwILBAQACAELAScDCQQBACIJAgstCgsNLQ4GDQAiDQINLQxGDQAiDQINLQ4KDScCDQQOLQgADi0KCRAACAANACUAAAvqLQIAAC0KEAszCgALAAkkAgAJAAACfyUAAA2tLQgBCScCCwQEAAgBCwEnAwkEAQAiCQILLQoLDS0OBw0AIg0CDS0MTw0AIg0CDS0ODA0nAg0EDi0IAA4tCgkQAAgADQAlAAAL6i0CAAAtChALCiILTAkKKgkFDSQCAA0AAALnJQAADb8eAgAJAC8qAAsACQANACILTwkeAgAOAC8qAAkADgAPACILUQ4eAgAQAC8qAA4AEAARHAoNEgQcChIQABwKEA0FHgIAEAAvKgALABAAEicCFwQYLQgAGC0KEhoACAAXACUAAA3RLQIAAC0KGhAtChsTLQocFC0KHRUtCh4WHgIAEgYMKhIWFyQCABcAAAOcIwAAA3oWChQXHAoUGAUcChcZBQQqGBUXBCoZCBgAKhcYAyMAAAO+FgoQFxwKEBgFHAoXGQUEKhgTFwQqGQgYACoXGAMjAAADvgAqEgMXDioSFxgkAgAYAAAD1SUAAA7vDCoSDQMWCgMNHAoDEgAcCg0DAAQqEg8NBCoDEQ8AKg0PAycCDwQYLQgAGC0KAxotCgobLQoXHC0KEB0tChMeLQoUHy0KFSAtChYhAAgADwAlAAAPAS0CAAAtChoNLQsNDwAiDwIPLQ4PDScCEAQYLQgAGC0KDRoACAAQACUAABBQLQIAAC0KGg8AIg1OEC0LEBAAIg1QES0LEREAIg1KEi0LEhIwCgAQAAswCgARAAkwCgASAA4AIgtGCTAKAA8ACRwKFwkAJwINBAUnAg8EAwAqDQ8OLQgBCwAIAQ4BJwMLBAEAIgsCDi0ODQ4AIg4CDi0ODQ4nAg4EAwAqCw4NLQoNDi0MRw4AIg4CDi0ODA4AIg4CDi0OAw4AIg4CDi0OCg4AIg4CDi0OCQ4nAgMEBQAiCwIKLQsKCicCDAQDACoLDAk3DgAKAAktCwQDACIDAgMtDgMEACIEAgktCwkJJwIKBAMAKgQKAzsOAAkAAyMAAAVJCiICRAMkAgADAAAFWyMAAAidLQgBCScCCgQCAAgBCgEnAwkEAQAiCQIKHzAATgBOAAoAIglOCi0LCgocCgoLBRwKCwkAHAoJCgUeAgAJAQoiCUkLFgoLDBwKDA0ABCoNCQwKKgsFCSQCAAkAAAXBJwINBAA8Bg0BHgIACQAtCAELJwINBAQACAENAScDCwQBACILAg0tCg0OLQ4GDgAiDgIOLQ4JDgAiDgIOLQ4MDicCCQQNLQgADS0KCw8ACAAJACUAAAvqLQIAAC0KDwYzCgAGAAkkAgAJAAAGKiUAAA2bDCIKSAYKKgYFCSQCAAkAAAZBJQAAEgEtCAEGJwIJBAQACAEJAScDBgQBACIGAgktCgkLLQ4HCwAiCwILLQxPCwAiCwILLQ4MCycCCwQMLQgADC0KBg4ACAALACUAAAvqLQIAAC0KDgkKIglMBgoqBgULJAIACwAABqklAAANvx4CAAYALyoACQAGAAsnAhAEES0IABEtCgsTAAgAEAAlAAAN0S0CAAAtChMGLQoUDC0KFQ0tChYOLQoXDx4CAAsGDCoLDxAkAgAQAAAHHiMAAAb8FgoNBhwKDQwFHAoGDQUEKgwOBgQqDQgMACoGDAMjAAAHQBYKBg0cCgYOBRwKDQYFBCoODA0EKgYIDAAqDQwDIwAAB0AMKgMKDCQCAAwAAAduIwAAB1ICKgMKBg4qCgMMJAIADAAAB2klAAASEyMAAAd8JwIMBQAtCgwGIwAAB3wAKgsGDA4qCwwNJAIADQAAB5MlAAAO7x4CAAYALyoACQAGAAsAIglPBh4CAA0ALyoABgANAA4AIglRDR4CAA8ALyoADQAPABAcCgsRBBwKEQ8AHAoPCwUnAhEEEi0IABItCg4ULQoQFS0KCxYtCE0XLQoDGC0ITRktCgoaLQoMGwAIABEAJQAADwEtAgAALQoUDy0LDwMAIgMCAy0OAw8nAgoEEC0IABAtCg8SAAgACgAlAAAQUC0CAAAtChIDACIPTgotCwoKACIPUAstCwsLACIPSgwtCwwMMAoACgAJMAoACwAGMAoADAANACIJRgYwCgADAAYtCwQDACIDAgMtDgMEACIEAgYtCwYGJwIJBAMAKgQJAzsOAAYAAyMAAAidCiICRQMkAgADAAAIryMAAAopHgIABAkkAgAEAAAIwSUAABIlHgIABAEtCAEGJwIJBAQACAEJAScDBgQBACIGAgktCgkKLQ4HCgAiCgIKLQxPCgAiCgIKLQ4ECicCBwQJLQgACS0KBgsACAAHACUAAAvqLQIAAC0KCwQKIgRMBgoqBgUHJAIABwAACS4lAAANvx4CAAYGHgIABwAvKgAEAAcACScCDQQOLQgADi0KCRAACAANACUAAA3RLQIAAC0KEAQtChEHLQoSCi0KEwstChQMDCoGDAkkAgAJAAAJoyMAAAmBFgoKBBwKCgYFHAoEBwUEKgYLBAQqBwgGACoEBgMjAAAJxRYKBAYcCgQJBRwKBgQFBCoJBwYEKgQIBwAqBgcDIwAACcUcCgMEACcCBgQBJwIIBAMAKgYIBy0IAQMACAEHAScDAwQBACIDAgctDgYHACIHAgctDgYHJwIHBAMAKgMHBi0KBgctDgQHACIDAgYtCwYGJwIHBAMAKgMHBDsOAAYABCMAAAopJwIDAlUnAgQCbicCBgJrJwIHAm8nAggCdycCCQIgJwIKAnMnAgsCZScCDAJsJwINAmMnAg4CdCcCDwJyJwIQAnsnAhECfS0IARInAhMEHAAIARMBJwMSBAEAIhICEy0KExQtDgMUACIUAhQtDgQUACIUAhQtDgYUACIUAhQtDgQUACIUAhQtDgcUACIUAhQtDggUACIUAhQtDgQUACIUAhQtDgkUACIUAhQtDgoUACIUAhQtDgsUACIUAhQtDgwUACIUAhQtDgsUACIUAhQtDg0UACIUAhQtDg4UACIUAhQtDgcUACIUAhQtDg8UACIUAhQtDgkUACIUAhQtDhAUACIUAhQtDgoUACIUAhQtDgsUACIUAhQtDgwUACIUAhQtDgsUACIUAhQtDg0UACIUAhQtDg4UACIUAhQtDgcUACIUAhQtDg8UACIUAhQtDhEUCiIFTQMkAgADAAAL6icCBAQeLQgBBicCBwQeAAgBBwEtCgYHKgMABwWGGhNb4cjsqQAiBwIHACISAggnAgkEGy0CCAMtAgcELQIJBSUAABI3JwIIBBsAKgcIBy0MTwcAIgcCBy0OAgcAIgcCBzwOBAYtCAEEJwIFBAUACAEFAScDBAQBACIEAgUtCgUGLQxMBgAiBgIGLQxMBgAiBgIGLQxMBgAiBgIGLQxSBi0ISwMjAAAMLgoiA0sFACIETgYtCwYGACIEUActCwcHJAIABQAADFcjAAAMUi0KBgImBCIDSgUGIgVKCQoqCQMIJAIACAAADHMlAAASaQwiBUoIJAIACAAADIUlAAASewAiAgIJACoJBQgtCwgIACoGCAktAgQDJwAEBAUlAAASjS0IBQYAIgZOCC0OCQgAIgVOCA4qBQgJJAIACQAADMolAAAO7wwiCEoJJAIACQAADNwlAAASewAiAgIKACoKCAktCwkJACoHCQgtAgYDJwAEBAUlAAASjS0IBQcAIgdQCS0OCAkAIgRKBi0LBgYAIgVQCA4qBQgJJAIACQAADSolAAAO7wwiCEoFJAIABQAADTwlAAASewAiAgIJACoJCAUtCwUFACoGBQgtAgcDJwAEBAUlAAASjS0IBQUAIgVKBi0OCAYtCAEEJwIGBAUACAEGAScDBAQBACIFAgYAIgQCBz8PAAYABwAiA04FLQoFAyMAAAwuKgEAAQXVEn0pwtLo7TwEAgEmKgEAAQWuko9rqY6SjDwEAgEmKgEAAQW6uyHXgjMYZDwEAgEmHAoCBAQcCgQDAAIqAgMELAIAAgAtXgmLgro3tDuZoTFhGP0g1C9RZsnp8T+16mWpbR4KbQQqBAIDHAoDBQQcCgUEAAIqAwQFBCoFAgMcCgMGAhwKBgUAHAoFBgIcCgYHARwKBwUCHAoFBgEcCgUHAAIqAwcILAIAAwAwM+okblBuiY6X9XDK/9cEywu0YDE/tyCynhOeXBAAAQQqCAMHHAoHCQQcCgkIAAIqBwgJBCoJAgccCgcJAhwKCQIAHAoCCQIcCgkKARwKCgICHAoCCQEcCgIKAAIqBwoLBCoLAwccCgcKBBwKCgMAHAoDBwUcCgIDBQQqAwcCHAoIAwUcCgUHBQQqBwMFHAoEAwUtCgYELQoDBi0KAgMtCgkCJioBAAEF0Afr9MvGZ5A8BAIBJhwKBAoAHAoJBAAnAgkAICcCDAQNLQgADS0IUQ8tCgkQAAgADAAlAAAS5y0CAAAtCg8LBCoECwkAKgoJBBwKBwkAJwIHAEAnAgsEDC0IAAwtCFEOLQoHDwAIAAsAJQAAEuctAgAALQoOCgQqCQoHACoEBwkcCggEACcCBwBIJwIKBAstCAALLQhRDS0KBw4ACAAKACUAABLnLQIAAC0KDQgEKgQIBwAqCQcEHAoFBwAnAgUAaCcCCQQKLQgACi0IUQwtCgUNAAgACQAlAAAS5y0CAAAtCgwIBCoHCAUAKgQFBxwKBgQAJwIFAHAnAggECS0IAAktCFELLQoFDAAIAAgAJQAAEuctAgAALQoLBgQqBAYFACoHBQQtCAEFJwIGBAQACAEGAScDBQQBACIFAgYtCgYHLQ4EBwAiBwIHLQ4CBwAiBwIHLQ4DBy0KBQImLQgBBCcCBQQFAAgBBQEnAwQEAQAiBAIFLQoFBi0MTAYAIgYCBi0MTAYAIgYCBi0MTAYAIgYCBi0MUgYtCEsDIwAAEJQKIgNLBQAiBE4GLQsGBgAiBFAHLQsHByQCAAUAABC9IwAAELgtCgYCJgQiA0oFBiIFSgkKKgkDCCQCAAgAABDZJQAAEmkMIgVKCCQCAAgAABDrJQAAEnsAIgICCQAqCQUILQsICAAqBggJLQIEAycABAQFJQAAEo0tCAUGACIGTggtDgkIACIFTggOKgUICSQCAAkAABEwJQAADu8MIghKCSQCAAkAABFCJQAAEnsAIgICCgAqCggJLQsJCQAqBwkILQIGAycABAQFJQAAEo0tCAUHACIHUAktDggJACIESgYtCwYGACIFUAgOKgUICSQCAAkAABGQJQAADu8MIghKBSQCAAUAABGiJQAAEnsAIgICCQAqCQgFLQsFBQAqBgUILQIHAycABAQFJQAAEo0tCAUFACIFSgYtDggGLQgBBCcCBgQFAAgBBgEnAwQEAQAiBQIGACIEAgc/DwAGAAcAIgNOBS0KBQMjAAAQlCoBAAEFXm0/LtzNhwk8BAIBJioBAAEFG7xl0D/c6tw8BAIBJioBAAEFT99KitfP8NM8BAIBJgAAAwUHLQADCC0ABAkjAAASWy0BCAYtBAYJAAAIAggAAAkCCQwACAcKJAAACgAAEkkmKgEAAQUFBBuZIK9gTDwEAgEmKgEAAQXkCFBFArWMHzwEAgEmLQEDBgoABgIHJAAABwAAEuItAAEFAAABBAEAAAMECS0AAwotAAULIwAAEsstAQoILQQICwAACgIKAAALAgsMAAoJDCQAAAwAABK5JwEFBAEjAAAS5i0AAwUmJwIHBAInAggBAS0IAQYnAgkEIQAIAQkBJwMGBAEAIgYCCScCCgQgQwOqAAMABwAKAAgACS0CCQMtAgoEJQAAE74nAgMEIScCBwQgLQhOBC0ITwUjAAATPwwqBAMIJAIACAAAE1YjAAATUS0KBQImBCoFBQgCKgcECQ4qBAcKJAIACgAAE3IlAAASEwwqCQcKJAIACgAAE4QlAAASewAiBgILACoLCQotCwoKHAoKCQAEKggCCgQqCQoLAihPCQoEKgoICQAqCwkFACIETggtCggEIwAAEz8tAAMHAAADBAgCAAgCCCMAABPrLQEHBS0BCAYtBAYHLQQFCAAABwIHAgAIAggMAAcICSQAAAkAABPRJg==",
103
- "debug_symbols": "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"
98
+ "bytecode": "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",
99
+ "debug_symbols": "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"
104
100
  },
105
101
  {
106
102
  "name": "publish_for_public_execution",
@@ -614,7 +610,7 @@
614
610
  "name": "inner",
615
611
  "type": {
616
612
  "kind": "struct",
617
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint",
613
+ "path": "aztec::protocol_types::point::Point",
618
614
  "fields": [
619
615
  {
620
616
  "name": "x",
@@ -650,7 +646,7 @@
650
646
  "name": "inner",
651
647
  "type": {
652
648
  "kind": "struct",
653
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint",
649
+ "path": "aztec::protocol_types::point::Point",
654
650
  "fields": [
655
651
  {
656
652
  "name": "x",
@@ -686,7 +682,7 @@
686
682
  "name": "inner",
687
683
  "type": {
688
684
  "kind": "struct",
689
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint",
685
+ "path": "aztec::protocol_types::point::Point",
690
686
  "fields": [
691
687
  {
692
688
  "name": "x",
@@ -722,7 +718,7 @@
722
718
  "name": "inner",
723
719
  "type": {
724
720
  "kind": "struct",
725
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint",
721
+ "path": "aztec::protocol_types::point::Point",
726
722
  "fields": [
727
723
  {
728
724
  "name": "x",
@@ -1432,7 +1428,7 @@
1432
1428
  "name": "pk_m",
1433
1429
  "type": {
1434
1430
  "kind": "struct",
1435
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint",
1431
+ "path": "aztec::protocol_types::point::Point",
1436
1432
  "fields": [
1437
1433
  {
1438
1434
  "name": "x",
@@ -2068,23 +2064,39 @@
2068
2064
  "error_kind": "string",
2069
2065
  "string": "Point not on curve"
2070
2066
  },
2067
+ "1560923443647584783": {
2068
+ "error_kind": "string",
2069
+ "string": "TpkM is the point at infinity"
2070
+ },
2071
+ "1911279422186654533": {
2072
+ "error_kind": "string",
2073
+ "string": "OvpkM is the point at infinity"
2074
+ },
2071
2075
  "4135474769840782447": {
2072
2076
  "error_kind": "string",
2073
2077
  "string": "Point at infinity should have canonical representation (0 0)"
2074
2078
  },
2079
+ "7264753475633835214": {
2080
+ "error_kind": "string",
2081
+ "string": "NpkM is the point at infinity"
2082
+ },
2075
2083
  "12469291177396340830": {
2076
2084
  "error_kind": "string",
2077
2085
  "string": "call to assert_max_bit_size"
2078
2086
  },
2087
+ "14483585040754951598": {
2088
+ "error_kind": "string",
2089
+ "string": "IvpkM is the point at infinity"
2090
+ },
2079
2091
  "14990209321349310352": {
2080
2092
  "error_kind": "string",
2081
2093
  "string": "attempt to add with overflow"
2082
2094
  }
2083
2095
  }
2084
2096
  },
2085
- "bytecode": "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",
2086
- "debug_symbols": "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",
2087
- "verification_key": "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"
2097
+ "bytecode": "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",
2098
+ "debug_symbols": "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",
2099
+ "verification_key": "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"
2088
2100
  },
2089
2101
  {
2090
2102
  "name": "set_update_delay",
@@ -2106,10 +2118,6 @@
2106
2118
  ],
2107
2119
  "return_type": null,
2108
2120
  "error_types": {
2109
- "361444214588792908": {
2110
- "error_kind": "string",
2111
- "string": "attempt to multiply with overflow"
2112
- },
2113
2121
  "1998584279744703196": {
2114
2122
  "error_kind": "string",
2115
2123
  "string": "attempt to subtract with overflow"
@@ -2136,8 +2144,8 @@
2136
2144
  }
2137
2145
  }
2138
2146
  },
2139
- "bytecode": "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",
2140
- "debug_symbols": "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"
2147
+ "bytecode": "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",
2148
+ "debug_symbols": "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"
2141
2149
  },
2142
2150
  {
2143
2151
  "name": "update",
@@ -2166,10 +2174,6 @@
2166
2174
  ],
2167
2175
  "return_type": null,
2168
2176
  "error_types": {
2169
- "361444214588792908": {
2170
- "error_kind": "string",
2171
- "string": "attempt to multiply with overflow"
2172
- },
2173
2177
  "1998584279744703196": {
2174
2178
  "error_kind": "string",
2175
2179
  "string": "attempt to subtract with overflow"
@@ -2196,8 +2200,8 @@
2196
2200
  }
2197
2201
  }
2198
2202
  },
2199
- "bytecode": "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",
2200
- "debug_symbols": "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"
2203
+ "bytecode": "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",
2204
+ "debug_symbols": "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"
2201
2205
  }
2202
2206
  ],
2203
2207
  "outputs": {
@@ -2294,7 +2298,7 @@
2294
2298
  }
2295
2299
  ],
2296
2300
  "kind": "struct",
2297
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2301
+ "path": "aztec::protocol_types::point::Point"
2298
2302
  }
2299
2303
  }
2300
2304
  ],
@@ -2330,7 +2334,7 @@
2330
2334
  }
2331
2335
  ],
2332
2336
  "kind": "struct",
2333
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2337
+ "path": "aztec::protocol_types::point::Point"
2334
2338
  }
2335
2339
  }
2336
2340
  ],
@@ -2366,7 +2370,7 @@
2366
2370
  }
2367
2371
  ],
2368
2372
  "kind": "struct",
2369
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2373
+ "path": "aztec::protocol_types::point::Point"
2370
2374
  }
2371
2375
  }
2372
2376
  ],
@@ -2402,7 +2406,7 @@
2402
2406
  }
2403
2407
  ],
2404
2408
  "kind": "struct",
2405
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2409
+ "path": "aztec::protocol_types::point::Point"
2406
2410
  }
2407
2411
  }
2408
2412
  ],
@@ -2588,7 +2592,7 @@
2588
2592
  }
2589
2593
  ],
2590
2594
  "kind": "struct",
2591
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2595
+ "path": "aztec::protocol_types::point::Point"
2592
2596
  }
2593
2597
  }
2594
2598
  ],
@@ -2624,7 +2628,7 @@
2624
2628
  }
2625
2629
  ],
2626
2630
  "kind": "struct",
2627
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2631
+ "path": "aztec::protocol_types::point::Point"
2628
2632
  }
2629
2633
  }
2630
2634
  ],
@@ -2660,7 +2664,7 @@
2660
2664
  }
2661
2665
  ],
2662
2666
  "kind": "struct",
2663
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2667
+ "path": "aztec::protocol_types::point::Point"
2664
2668
  }
2665
2669
  }
2666
2670
  ],
@@ -2696,7 +2700,7 @@
2696
2700
  }
2697
2701
  ],
2698
2702
  "kind": "struct",
2699
- "path": "std::embedded_curve_ops::EmbeddedCurvePoint"
2703
+ "path": "aztec::protocol_types::point::Point"
2700
2704
  }
2701
2705
  }
2702
2706
  ],
@@ -2799,181 +2803,177 @@
2799
2803
  "function_locations": [
2800
2804
  {
2801
2805
  "name": "<impl Empty for AztecAddress>::empty",
2802
- "start": 939
2806
+ "start": 842
2803
2807
  },
2804
2808
  {
2805
2809
  "name": "<impl ToField for AztecAddress>::to_field",
2806
- "start": 1039
2810
+ "start": 942
2807
2811
  },
2808
2812
  {
2809
2813
  "name": "<impl FromField for AztecAddress>::from_field",
2810
- "start": 1151
2814
+ "start": 1054
2811
2815
  },
2812
2816
  {
2813
2817
  "name": "AztecAddress::zero",
2814
- "start": 1246
2818
+ "start": 1149
2815
2819
  },
2816
2820
  {
2817
2821
  "name": "AztecAddress::is_valid",
2818
- "start": 1576
2822
+ "start": 1479
2819
2823
  },
2820
2824
  {
2821
2825
  "name": "AztecAddress::to_address_point",
2822
- "start": 1951
2826
+ "start": 1854
2823
2827
  },
2824
2828
  {
2825
2829
  "name": "AztecAddress::is_positive",
2826
- "start": 2604
2830
+ "start": 2507
2827
2831
  },
2828
2832
  {
2829
2833
  "name": "AztecAddress::get_y",
2830
- "start": 3460
2834
+ "start": 3363
2831
2835
  },
2832
2836
  {
2833
2837
  "name": "AztecAddress::compute",
2834
- "start": 3846
2838
+ "start": 3749
2835
2839
  },
2836
2840
  {
2837
2841
  "name": "AztecAddress::compute_from_class_id",
2838
- "start": 7868
2842
+ "start": 7971
2839
2843
  },
2840
2844
  {
2841
2845
  "name": "AztecAddress::is_zero",
2842
- "start": 8140
2846
+ "start": 8243
2843
2847
  },
2844
2848
  {
2845
2849
  "name": "AztecAddress::assert_is_zero",
2846
- "start": 8205
2850
+ "start": 8308
2847
2851
  },
2848
2852
  {
2849
2853
  "name": "check_max_field_value",
2850
- "start": 8289
2854
+ "start": 8392
2851
2855
  },
2852
2856
  {
2853
2857
  "name": "check_is_positive",
2854
- "start": 8400
2858
+ "start": 8503
2855
2859
  },
2856
2860
  {
2857
2861
  "name": "check_embedded_curve_point_add",
2858
- "start": 8921
2862
+ "start": 9024
2859
2863
  },
2860
2864
  {
2861
2865
  "name": "check_embedded_curve_point_add_2",
2862
- "start": 9338
2866
+ "start": 9441
2863
2867
  },
2864
2868
  {
2865
2869
  "name": "compute_address_from_partial_and_pub_keys",
2866
- "start": 9567
2870
+ "start": 9670
2867
2871
  },
2868
2872
  {
2869
2873
  "name": "compute_preaddress_from_partial_and_pub_keys",
2870
- "start": 11398
2874
+ "start": 11501
2871
2875
  },
2872
2876
  {
2873
2877
  "name": "from_field_to_field",
2874
- "start": 11747
2878
+ "start": 11850
2875
2879
  },
2876
2880
  {
2877
2881
  "name": "serde",
2878
- "start": 11884
2882
+ "start": 11987
2879
2883
  },
2880
2884
  {
2881
2885
  "name": "to_address_point_valid",
2882
- "start": 12290
2886
+ "start": 12393
2883
2887
  },
2884
2888
  {
2885
2889
  "name": "to_address_point_invalid",
2886
- "start": 12954
2890
+ "start": 13057
2887
2891
  }
2888
2892
  ],
2889
2893
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr",
2890
- "source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{AZTEC_ADDRESS_LENGTH, DOM_SEP__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE},\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::sqrt,\n};\n\n// We do below because `use crate::point::Point;` does not work\nuse std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n /// Returns `true` if the address is valid.\n ///\n /// An invalid address is one that can be proven to not be correctly derived, meaning it contains no contract code,\n /// public keys, etc., and can therefore not receive messages nor execute calls.\n pub fn is_valid(self) -> bool {\n self.get_y().is_some()\n }\n\n /// Returns an address's [`AddressPoint`].\n ///\n /// This can be used to create shared secrets with the owner of the address. If the address is invalid (see\n /// [`AztecAddress::is_valid`]) then this returns `Option::none()`, and no shared secrets can be created.\n pub fn to_address_point(self) -> Option<AddressPoint> {\n self.get_y().map(|y| {\n // If we get a negative y coordinate (y > (r - 1) / 2), we swap it to the\n // positive one (where y <= (r - 1) / 2) by negating it.\n let final_y = if Self::is_positive(y) { y } else { -y };\n\n AddressPoint { inner: Point { x: self.inner, y: final_y, is_infinite: false } }\n })\n }\n\n /// Determines whether a y-coordinate is in the lower (positive) or upper (negative) \"half\" of the field.\n /// I.e.\n /// y <= (r - 1)/2 => positive.\n /// y > (r - 1)/2 => negative.\n /// An AddressPoint always uses the \"positive\" y.\n fn is_positive(y: Field) -> bool {\n // Note: The field modulus r is MAX_FIELD_VALUE + 1.\n let MID = MAX_FIELD_VALUE / 2; // (r - 1) / 2\n let MID_PLUS_1 = MID + 1; // (r - 1)/2 + 1\n // Note: y <= m implies y < m + 1.\n y.lt(MID_PLUS_1)\n }\n\n /// Returns one of the two possible y-coordinates.\n ///\n /// Not all `AztecAddresses` are valid, in which case there is no corresponding y-coordinate. This returns\n /// `Option::none()` for invalid addresses.\n ///\n /// An `AztecAddress` is defined by an x-coordinate, for which two y-coordinates exist as solutions to the curve\n /// equation. This function returns either of them. Note that an [`AddressPoint`] must **always** have a positive\n /// y-coordinate - if trying to obtain the underlying point use [`AztecAddress::to_address_point`] instead.\n fn get_y(self) -> Option<Field> {\n // We compute the address point by taking our address as x, and then solving for y in the\n // equation which defines the grumpkin curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = x * x * x - 17;\n\n sqrt(y_squared)\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n //\n // address = address_point.x\n // |\n // address_point = pre_address * G + Ivpk_m (always choose \"positive\" y-coord)\n // | ^\n // | |.....................\n // pre_address .\n // / \\ .\n // / \\ .\n // partial_address public_keys_hash .\n // / \\ / / \\ \\ .\n // / \\ Npk_m Ivpk_m Ovpk_m Tpk_m .\n // contract_class_id \\ |...................\n // / | \\ \\\n // artifact_hash | public_bytecode_commitment salted_initialization_hash\n // | / / \\\n // private_function_tree_root deployer_address salt initialization_hash\n // / \\ / \\\n // ... ... constructor_fn_selector constructor_args_hash\n // / \\\n // / \\ / \\\n // leaf leaf leaf leaf\n // ^\n // |\n // |---h(function_selector, vk_hash)\n // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n // Each of these represents a private function of the contract.\n\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n DOM_SEP__CONTRACT_ADDRESS_V1,\n );\n\n // Note: `.add()` will fail within the blackbox fn if either of the points are not on the curve. (See tests below).\n let address_point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address)).add(\n public_keys.ivpk_m.to_point(),\n );\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n#[test]\nfn check_max_field_value() {\n // Check that it is indeed r-1.\n assert_eq(MAX_FIELD_VALUE + 1, 0);\n}\n\n#[test]\nfn check_is_positive() {\n assert(AztecAddress::is_positive(0));\n assert(AztecAddress::is_positive(1));\n assert(!AztecAddress::is_positive(-1));\n assert(AztecAddress::is_positive(MAX_FIELD_VALUE / 2));\n assert(!AztecAddress::is_positive((MAX_FIELD_VALUE / 2) + 1));\n}\n\n// Gives us confidence that we don't need to manually check that the input public keys need to be on the curve for `add`,\n// because the blackbox function does this check for us.\n#[test(should_fail_with = \"is not on curve\")]\nfn check_embedded_curve_point_add() {\n // Choose a point not on the curve:\n let p1 = Point { x: 1, y: 1, is_infinite: false };\n let p2 = Point::generator();\n let _ = p1 + p2;\n}\n\n// Gives us confidence that we don't need to manually check that the input public keys need to be on the curve for `add`,\n// because the blackbox function does this check for us.\n#[test(should_fail_with = \"is not on curve\")]\nfn check_embedded_curve_point_add_2() {\n // Choose a point not on the curve in the 2nd position.\n let p1 = Point::generator();\n let p2 = Point { x: 1, y: 1, is_infinite: false };\n let _ = p1 + p2;\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x2f66081d4bb077fbe8e8abe96a3516a713a3d7e34360b4e985da0da95092b37d;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], DOM_SEP__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x286c7755f2924b1e53b00bcaf1adaffe7287bd74bba7a02f4ab867e3892d28da;\n assert(pre_address == expected_computed_preaddress_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n\n#[test]\nfn to_address_point_valid() {\n // x = 8 where x^3 - 17 = 512 - 17 = 495, which is a residue in this field\n let address = AztecAddress { inner: 8 };\n\n assert(address.get_y().is_some()); // We don't bother checking the result of get_y as it is only used internally\n assert(address.is_valid());\n\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_some());\n\n let point = maybe_point.unwrap().inner;\n // check that x is preserved\n assert_eq(point.x, Field::from(8));\n\n // check that the curve equation holds: y^2 == x^3 - 17\n assert_eq(point.y * point.y, point.x * point.x * point.x - 17);\n}\n\n#[test]\nunconstrained fn to_address_point_invalid() {\n // x = 3 where x^3 - 17 = 27 - 17 = 10, which is a non-residue in this field\n let address = AztecAddress { inner: 3 };\n\n assert(address.get_y().is_none());\n assert(!address.is_valid());\n\n assert(address.to_address_point().is_none());\n}\n"
2894
+ "source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{AZTEC_ADDRESS_LENGTH, DOM_SEP__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE},\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::sqrt,\n};\n\nuse crate::point::Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n /// Returns `true` if the address is valid.\n ///\n /// An invalid address is one that can be proven to not be correctly derived, meaning it contains no contract code,\n /// public keys, etc., and can therefore not receive messages nor execute calls.\n pub fn is_valid(self) -> bool {\n self.get_y().is_some()\n }\n\n /// Returns an address's [`AddressPoint`].\n ///\n /// This can be used to create shared secrets with the owner of the address. If the address is invalid (see\n /// [`AztecAddress::is_valid`]) then this returns `Option::none()`, and no shared secrets can be created.\n pub fn to_address_point(self) -> Option<AddressPoint> {\n self.get_y().map(|y| {\n // If we get a negative y coordinate (y > (r - 1) / 2), we swap it to the\n // positive one (where y <= (r - 1) / 2) by negating it.\n let final_y = if Self::is_positive(y) { y } else { -y };\n\n AddressPoint { inner: Point { x: self.inner, y: final_y, is_infinite: false } }\n })\n }\n\n /// Determines whether a y-coordinate is in the lower (positive) or upper (negative) \"half\" of the field.\n /// I.e.\n /// y <= (r - 1)/2 => positive.\n /// y > (r - 1)/2 => negative.\n /// An AddressPoint always uses the \"positive\" y.\n fn is_positive(y: Field) -> bool {\n // Note: The field modulus r is MAX_FIELD_VALUE + 1.\n let MID = MAX_FIELD_VALUE / 2; // (r - 1) / 2\n let MID_PLUS_1 = MID + 1; // (r - 1)/2 + 1\n // Note: y <= m implies y < m + 1.\n y.lt(MID_PLUS_1)\n }\n\n /// Returns one of the two possible y-coordinates.\n ///\n /// Not all `AztecAddresses` are valid, in which case there is no corresponding y-coordinate. This returns\n /// `Option::none()` for invalid addresses.\n ///\n /// An `AztecAddress` is defined by an x-coordinate, for which two y-coordinates exist as solutions to the curve\n /// equation. This function returns either of them. Note that an [`AddressPoint`] must **always** have a positive\n /// y-coordinate - if trying to obtain the underlying point use [`AztecAddress::to_address_point`] instead.\n fn get_y(self) -> Option<Field> {\n // We compute the address point by taking our address as x, and then solving for y in the\n // equation which defines the grumpkin curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = x * x * x - 17;\n\n sqrt(y_squared)\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n //\n // address = address_point.x\n // |\n // address_point = pre_address * G + Ivpk_m (always choose \"positive\" y-coord)\n // | ^\n // | |.....................\n // pre_address .\n // / \\ .\n // / \\ .\n // partial_address public_keys_hash .\n // / \\ / / \\ \\ .\n // / \\ Npk_m Ivpk_m Ovpk_m Tpk_m .\n // contract_class_id \\ |...................\n // / | \\ \\\n // artifact_hash | public_bytecode_commitment salted_initialization_hash\n // | / / \\\n // private_function_tree_root deployer_address salt initialization_hash\n // / \\ / \\\n // ... ... constructor_fn_selector constructor_args_hash\n // / \\\n // / \\ / \\\n // leaf leaf leaf leaf\n // ^\n // |\n // |---h(function_selector, vk_hash)\n // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n // Each of these represents a private function of the contract.\n\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n DOM_SEP__CONTRACT_ADDRESS_V1,\n );\n\n // Note: `.add()` will fail within the blackbox fn if either of the points are not on the curve. (See tests below).\n // TODO(F-553): Drop the `.to_embedded()` / `.into()` round-trip once the custom `Point` wrapper is removed and\n // we use `EmbeddedCurvePoint` directly.\n let address_point: Point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address))\n .add(public_keys.ivpk_m.to_point().to_embedded())\n .into();\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n#[test]\nfn check_max_field_value() {\n // Check that it is indeed r-1.\n assert_eq(MAX_FIELD_VALUE + 1, 0);\n}\n\n#[test]\nfn check_is_positive() {\n assert(AztecAddress::is_positive(0));\n assert(AztecAddress::is_positive(1));\n assert(!AztecAddress::is_positive(-1));\n assert(AztecAddress::is_positive(MAX_FIELD_VALUE / 2));\n assert(!AztecAddress::is_positive((MAX_FIELD_VALUE / 2) + 1));\n}\n\n// Gives us confidence that we don't need to manually check that the input public keys need to be on the curve for `add`,\n// because the blackbox function does this check for us.\n#[test(should_fail_with = \"is not on curve\")]\nfn check_embedded_curve_point_add() {\n // Choose a point not on the curve:\n let p1 = Point { x: 1, y: 1, is_infinite: false };\n let p2 = Point::generator();\n let _ = p1 + p2;\n}\n\n// Gives us confidence that we don't need to manually check that the input public keys need to be on the curve for `add`,\n// because the blackbox function does this check for us.\n#[test(should_fail_with = \"is not on curve\")]\nfn check_embedded_curve_point_add_2() {\n // Choose a point not on the curve in the 2nd position.\n let p1 = Point::generator();\n let p2 = Point { x: 1, y: 1, is_infinite: false };\n let _ = p1 + p2;\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x2f66081d4bb077fbe8e8abe96a3516a713a3d7e34360b4e985da0da95092b37d;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], DOM_SEP__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x286c7755f2924b1e53b00bcaf1adaffe7287bd74bba7a02f4ab867e3892d28da;\n assert(pre_address == expected_computed_preaddress_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n\n#[test]\nfn to_address_point_valid() {\n // x = 8 where x^3 - 17 = 512 - 17 = 495, which is a residue in this field\n let address = AztecAddress { inner: 8 };\n\n assert(address.get_y().is_some()); // We don't bother checking the result of get_y as it is only used internally\n assert(address.is_valid());\n\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_some());\n\n let point = maybe_point.unwrap().inner;\n // check that x is preserved\n assert_eq(point.x, Field::from(8));\n\n // check that the curve equation holds: y^2 == x^3 - 17\n assert_eq(point.y * point.y, point.x * point.x * point.x - 17);\n}\n\n#[test]\nunconstrained fn to_address_point_invalid() {\n // x = 3 where x^3 - 17 = 27 - 17 = 10, which is a non-residue in this field\n let address = AztecAddress { inner: 3 };\n\n assert(address.get_y().is_none());\n assert(!address.is_valid());\n\n assert(address.to_address_point().is_none());\n}\n"
2891
2895
  },
2892
2896
  "15": {
2893
2897
  "function_locations": [
2894
2898
  {
2895
2899
  "name": "EmbeddedCurvePoint::double",
2896
- "start": 611
2900
+ "start": 559
2897
2901
  },
2898
2902
  {
2899
2903
  "name": "EmbeddedCurvePoint::point_at_infinity",
2900
- "start": 783
2904
+ "start": 731
2901
2905
  },
2902
2906
  {
2903
2907
  "name": "EmbeddedCurvePoint::generator",
2904
- "start": 943
2908
+ "start": 872
2909
+ },
2910
+ {
2911
+ "name": "EmbeddedCurvePoint::is_infinite",
2912
+ "start": 1183
2905
2913
  },
2906
2914
  {
2907
2915
  "name": "<impl Add for EmbeddedCurvePoint>::add",
2908
- "start": 1397
2916
+ "start": 1430
2909
2917
  },
2910
2918
  {
2911
2919
  "name": "<impl Sub for EmbeddedCurvePoint>::sub",
2912
- "start": 1614
2920
+ "start": 1647
2913
2921
  },
2914
2922
  {
2915
2923
  "name": "<impl Neg for EmbeddedCurvePoint>::neg",
2916
- "start": 1872
2924
+ "start": 1905
2917
2925
  },
2918
2926
  {
2919
2927
  "name": "<impl Eq for EmbeddedCurvePoint>::eq",
2920
- "start": 2097
2928
+ "start": 2099
2921
2929
  },
2922
2930
  {
2923
2931
  "name": "<impl Hash for EmbeddedCurvePoint>::hash",
2924
- "start": 2356
2932
+ "start": 2269
2925
2933
  },
2926
2934
  {
2927
2935
  "name": "EmbeddedCurveScalar::new",
2928
- "start": 3017
2936
+ "start": 2823
2929
2937
  },
2930
2938
  {
2931
2939
  "name": "EmbeddedCurveScalar::from_field",
2932
- "start": 3202
2940
+ "start": 3008
2933
2941
  },
2934
2942
  {
2935
2943
  "name": "EmbeddedCurveScalar::from_bytes",
2936
- "start": 3548
2944
+ "start": 3354
2937
2945
  },
2938
2946
  {
2939
2947
  "name": "<impl Eq for EmbeddedCurveScalar>::eq",
2940
- "start": 3994
2948
+ "start": 3800
2941
2949
  },
2942
2950
  {
2943
2951
  "name": "<impl Hash for EmbeddedCurveScalar>::hash",
2944
- "start": 4177
2952
+ "start": 3983
2945
2953
  },
2946
2954
  {
2947
2955
  "name": "multi_scalar_mul",
2948
- "start": 4921
2956
+ "start": 4659
2949
2957
  },
2950
2958
  {
2951
- "name": "multi_scalar_mul_array_return_blackbox",
2952
- "start": 5190
2959
+ "name": "fixed_base_scalar_mul",
2960
+ "start": 4874
2953
2961
  },
2954
2962
  {
2955
2963
  "name": "multi_scalar_mul_array_return",
2956
- "start": 5356
2957
- },
2958
- {
2959
- "name": "fixed_base_scalar_mul",
2960
- "start": 5675
2964
+ "start": 5157
2961
2965
  },
2962
2966
  {
2963
2967
  "name": "embedded_curve_add",
2964
- "start": 6197
2968
+ "start": 5612
2965
2969
  },
2966
2970
  {
2967
2971
  "name": "embedded_curve_add_array_return",
2968
- "start": 6788
2969
- },
2970
- {
2971
- "name": "embedded_curve_add_inner",
2972
- "start": 6958
2972
+ "start": 5897
2973
2973
  }
2974
2974
  ],
2975
2975
  "path": "std/embedded_curve_ops.nr",
2976
- "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash<H>(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n /// Create a new scalar using the provided (lo, hi) pair\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n /// Create a scalar from the given bn254 field value\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n /// Take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash<H>(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n/// Computes a multi scalar multiplication over the embedded curve.\n/// For bn254, We have Grumpkin and Baby JubJub.\n/// For bls12-381, we have JubJub and Bandersnatch.\n///\n/// The embedded curve being used is decided by the\n/// underlying proof system.\n///\n/// IMPORTANT: Prefer `multi_scalar_mul()` over repeated `embedded_curve_add()`\n/// for adding multiple points. This is significantly more efficient.\n/// For adding exactly 2 points, use `embedded_curve_add()` directly.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul<let N: u32>(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\nfn multi_scalar_mul_array_return_blackbox<let N: u32>(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\npub(crate) fn multi_scalar_mul_array_return<let N: u32>(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {\n let mut result = multi_scalar_mul_array_return_blackbox(points, scalars, true);\n result[0].is_infinite = (result[0].x == 0) & (result[0].y == 0);\n result\n}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// Elliptic curve addition\n/// IMPORTANT: this function is expected to perform a full addition in order to handle all corner cases:\n/// - points on the curve\n/// - point doubling\n/// - point at infinity\n/// As a result, you may not get optimal performance, depending on the assumptions of your inputs.\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // avoid calling the black box function for trivial cases\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_inner(point1, point2)\n }\n } else {\n embedded_curve_add_inner(point1, point2)\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n _predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// EC addition wrapper for the foreign function\nfn embedded_curve_add_inner(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n let mut result = embedded_curve_add_array_return(point1, point2, true)[0];\n result.is_infinite = (result.x == 0) & (result.y == 0);\n result\n}\n"
2976
+ "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0 }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n }\n }\n\n /// True if this point is the point at infinity\n pub fn is_infinite(self) -> bool {\n (self.x == 0) & (self.y == 0)\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.x == b.x) & (self.y == b.y)\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash<H>(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.x.hash(state);\n self.y.hash(state);\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n /// Create a new scalar using the provided (lo, hi) pair\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n /// Create a scalar from the given bn254 field value\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n /// Take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash<H>(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n/// Computes a multi scalar multiplication over the embedded curve.\n/// For bn254, We have Grumpkin.\n///\n/// The embedded curve being used is decided by the\n/// underlying proof system.\n///\n/// IMPORTANT: Prefer `multi_scalar_mul()` over repeated `embedded_curve_add()`\n/// for adding multiple points. This is significantly more efficient.\n/// For adding exactly 2 points, use `embedded_curve_add()` directly.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul<let N: u32>(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars, true)[0]\n}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return<let N: u32>(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// Elliptic curve addition\n/// IMPORTANT: this function is expected to perform a full addition in order to handle all corner cases:\n/// - points on the curve\n/// - point doubling\n/// - point at infinity\n/// As a result, you may not get optimal performance, depending on the assumptions of your inputs.\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n embedded_curve_add_array_return(point1, point2, true)[0]\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n _predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n"
2977
2977
  },
2978
2978
  "151": {
2979
2979
  "function_locations": [
@@ -3117,215 +3117,215 @@
3117
3117
  },
3118
3118
  {
3119
3119
  "name": "Field::to_le_bits",
3120
- "start": 1192
3120
+ "start": 1196
3121
3121
  },
3122
3122
  {
3123
3123
  "name": "Field::to_be_bits",
3124
- "start": 2384
3124
+ "start": 2387
3125
3125
  },
3126
3126
  {
3127
3127
  "name": "Field::to_le_bytes",
3128
- "start": 3564
3128
+ "start": 3562
3129
3129
  },
3130
3130
  {
3131
3131
  "name": "Field::to_be_bytes",
3132
- "start": 5035
3132
+ "start": 5033
3133
3133
  },
3134
3134
  {
3135
3135
  "name": "Field::to_le_radix",
3136
- "start": 5906
3136
+ "start": 5904
3137
3137
  },
3138
3138
  {
3139
3139
  "name": "Field::to_be_radix",
3140
- "start": 6364
3140
+ "start": 6362
3141
3141
  },
3142
3142
  {
3143
3143
  "name": "Field::pow_32",
3144
- "start": 7055
3144
+ "start": 7053
3145
3145
  },
3146
3146
  {
3147
3147
  "name": "Field::sgn0",
3148
- "start": 7446
3148
+ "start": 7455
3149
3149
  },
3150
3150
  {
3151
3151
  "name": "Field::lt",
3152
- "start": 7518
3152
+ "start": 7538
3153
3153
  },
3154
3154
  {
3155
3155
  "name": "Field::from_le_bytes",
3156
- "start": 7898
3156
+ "start": 7918
3157
3157
  },
3158
3158
  {
3159
3159
  "name": "Field::from_be_bytes",
3160
- "start": 8456
3160
+ "start": 8476
3161
3161
  },
3162
3162
  {
3163
3163
  "name": "__assert_max_bit_size",
3164
- "start": 8737
3164
+ "start": 8757
3165
3165
  },
3166
3166
  {
3167
3167
  "name": "__to_le_radix",
3168
- "start": 8865
3168
+ "start": 8885
3169
3169
  },
3170
3170
  {
3171
3171
  "name": "__to_be_radix",
3172
- "start": 8993
3172
+ "start": 9013
3173
3173
  },
3174
3174
  {
3175
3175
  "name": "__to_le_bits",
3176
- "start": 9710
3176
+ "start": 9734
3177
3177
  },
3178
3178
  {
3179
3179
  "name": "__to_be_bits",
3180
- "start": 10424
3180
+ "start": 10452
3181
3181
  },
3182
3182
  {
3183
3183
  "name": "modulus_num_bits",
3184
- "start": 10499
3184
+ "start": 10527
3185
3185
  },
3186
3186
  {
3187
3187
  "name": "modulus_be_bits",
3188
- "start": 10573
3188
+ "start": 10603
3189
3189
  },
3190
3190
  {
3191
3191
  "name": "modulus_le_bits",
3192
- "start": 10647
3192
+ "start": 10679
3193
3193
  },
3194
3194
  {
3195
3195
  "name": "modulus_be_bytes",
3196
- "start": 10723
3196
+ "start": 10755
3197
3197
  },
3198
3198
  {
3199
3199
  "name": "modulus_le_bytes",
3200
- "start": 10799
3200
+ "start": 10831
3201
3201
  },
3202
3202
  {
3203
3203
  "name": "__field_less_than",
3204
- "start": 10960
3204
+ "start": 10992
3205
3205
  },
3206
3206
  {
3207
3207
  "name": "field_less_than",
3208
- "start": 11036
3208
+ "start": 11068
3209
3209
  },
3210
3210
  {
3211
3211
  "name": "bytes32_to_field",
3212
- "start": 11178
3212
+ "start": 11210
3213
3213
  },
3214
3214
  {
3215
3215
  "name": "lt_fallback",
3216
- "start": 11585
3216
+ "start": 11617
3217
3217
  },
3218
3218
  {
3219
3219
  "name": "tests::test_to_be_bits",
3220
- "start": 12547
3220
+ "start": 12579
3221
3221
  },
3222
3222
  {
3223
3223
  "name": "tests::test_to_le_bits",
3224
- "start": 12787
3224
+ "start": 12852
3225
3225
  },
3226
3226
  {
3227
3227
  "name": "tests::test_to_be_bytes",
3228
- "start": 13029
3228
+ "start": 13127
3229
3229
  },
3230
3230
  {
3231
3231
  "name": "tests::test_to_le_bytes",
3232
- "start": 13335
3232
+ "start": 13433
3233
3233
  },
3234
3234
  {
3235
3235
  "name": "tests::test_to_be_radix",
3236
- "start": 13641
3236
+ "start": 13739
3237
3237
  },
3238
3238
  {
3239
3239
  "name": "tests::test_to_le_radix",
3240
- "start": 14223
3240
+ "start": 14321
3241
3241
  },
3242
3242
  {
3243
3243
  "name": "tests::test_to_le_radix_1",
3244
- "start": 14823
3244
+ "start": 14921
3245
3245
  },
3246
3246
  {
3247
3247
  "name": "tests::test_to_le_radix_brillig_1",
3248
- "start": 15276
3248
+ "start": 15374
3249
3249
  },
3250
3250
  {
3251
3251
  "name": "tests::test_to_le_radix_3",
3252
- "start": 15630
3252
+ "start": 15728
3253
3253
  },
3254
3254
  {
3255
3255
  "name": "tests::test_to_le_radix_brillig_3",
3256
- "start": 15941
3256
+ "start": 16039
3257
3257
  },
3258
3258
  {
3259
3259
  "name": "tests::test_to_le_radix_512",
3260
- "start": 16369
3260
+ "start": 16467
3261
3261
  },
3262
3262
  {
3263
3263
  "name": "tests::not_enough_limbs_brillig",
3264
- "start": 16778
3264
+ "start": 16876
3265
3265
  },
3266
3266
  {
3267
3267
  "name": "tests::not_enough_limbs",
3268
- "start": 16974
3268
+ "start": 17072
3269
3269
  },
3270
3270
  {
3271
3271
  "name": "tests::test_field_less_than",
3272
- "start": 17116
3272
+ "start": 17214
3273
3273
  },
3274
3274
  {
3275
3275
  "name": "tests::test_large_field_values_unconstrained",
3276
- "start": 17371
3276
+ "start": 17469
3277
3277
  },
3278
3278
  {
3279
3279
  "name": "tests::test_large_field_values",
3280
- "start": 17819
3280
+ "start": 17922
3281
3281
  },
3282
3282
  {
3283
3283
  "name": "tests::test_decomposition_edge_cases",
3284
- "start": 18261
3284
+ "start": 18369
3285
3285
  },
3286
3286
  {
3287
3287
  "name": "tests::test_pow_32",
3288
- "start": 18775
3288
+ "start": 18959
3289
3289
  },
3290
3290
  {
3291
3291
  "name": "tests::test_sgn0",
3292
- "start": 19104
3292
+ "start": 19288
3293
3293
  },
3294
3294
  {
3295
3295
  "name": "tests::test_bit_decomposition_overflow",
3296
- "start": 19498
3296
+ "start": 19710
3297
3297
  },
3298
3298
  {
3299
3299
  "name": "tests::test_byte_decomposition_overflow",
3300
- "start": 19778
3300
+ "start": 19992
3301
3301
  },
3302
3302
  {
3303
3303
  "name": "tests::test_to_from_be_bytes_bn254_edge_cases",
3304
- "start": 19995
3304
+ "start": 20209
3305
3305
  },
3306
3306
  {
3307
3307
  "name": "tests::test_to_from_le_bytes_bn254_edge_cases",
3308
- "start": 21946
3308
+ "start": 22160
3309
3309
  },
3310
3310
  {
3311
3311
  "name": "tests::from_le_bits",
3312
- "start": 24029
3312
+ "start": 24245
3313
3313
  },
3314
3314
  {
3315
3315
  "name": "tests::from_be_bits",
3316
- "start": 24574
3316
+ "start": 24792
3317
3317
  },
3318
3318
  {
3319
3319
  "name": "tests::test_to_from_be_bits_bn254_edge_cases",
3320
- "start": 24820
3320
+ "start": 25038
3321
3321
  },
3322
3322
  {
3323
3323
  "name": "tests::test_to_from_le_bits_bn254_edge_cases",
3324
- "start": 26734
3324
+ "start": 26971
3325
3325
  }
3326
3326
  ],
3327
3327
  "path": "std/field/mod.nr",
3328
- "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<let BIT_SIZE: u32>(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 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 array 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<let N: u32>(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 array 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<let N: u32>(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<let N: u32>(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<let N: u32>(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<let N: u32>(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<let N: u32>(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<let N: u32>(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<let N: u32>(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<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little 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 array 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<let N: u32>(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 array 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<let N: u32>(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(\"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(\"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(\"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(\"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<let N: u32>(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<let N: u32>(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"
3328
+ "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<let BIT_SIZE: u32>(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 `[bool; 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 array 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<let N: u32>(self: Self) -> [bool; 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]);\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 `[bool; 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 array 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<let N: u32>(self: Self) -> [bool; 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]);\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<let N: u32>(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<let N: u32>(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<let N: u32>(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<let N: u32>(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: [bool; 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) = false if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = true.\n pub fn sgn0(self) -> bool {\n (self as u8) % 2 == 1\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<let N: u32>(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<let N: u32>(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<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[bool; 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 array 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<let N: u32>(value: Field) -> [bool; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[bool; 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 array 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<let N: u32>(value: Field) -> [bool; 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() -> [bool] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [bool] {}\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: [bool; 8] = field.to_be_bits();\n assert_eq(bits, [false, false, false, false, false, false, true, false]);\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: [bool; 8] = field.to_le_bits();\n assert_eq(bits, [false, true, false, false, false, false, false, false]);\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(\"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(\"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(\"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(\"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: [bool; 64] = large_field.to_le_bits();\n assert_eq(bits[0], true);\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: [bool; 64] = large_val.to_le_bits();\n assert_eq(bits[0], true);\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: [bool; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [false; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [bool; 8] = 1.to_le_bits();\n let expected: [bool; 8] = [true, false, false, false, false, false, false, false];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [bool; 8] = 4.to_le_bits();\n let expected: [bool; 8] = [false, false, true, false, false, false, false, false];\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(), false);\n assert_eq(2.sgn0(), false);\n assert_eq(4.sgn0(), false);\n assert_eq(100.sgn0(), false);\n\n assert_eq(1.sgn0(), true);\n assert_eq(3.sgn0(), true);\n assert_eq(5.sgn0(), true);\n assert_eq(101.sgn0(), true);\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 _: [bool; 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<let N: u32>(bits: [bool; 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<let N: u32>(bits: [bool; 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: [bool; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1]);\n p_minus_1_bits[254 - 1] = false;\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: [bool; 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: [bool; 254] = modulus_be_bits().as_array();\n assert(!p_plus_4_bits[254 - 3]);\n p_plus_4_bits[254 - 3] = true;\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: [bool; 254] = p_plus_4.to_be_bits();\n assert(p_plus_4_converted_bits[254 - 3]);\n p_plus_4_converted_bits[254 - 3] = false;\n assert_eq(p_plus_4_converted_bits, [false; 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 bits produces 254 false values\n let p_bits: [bool; 254] = 0.to_be_bits();\n assert_eq(p_bits, [false; 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: [bool; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0]);\n p_minus_1_bits[0] = false;\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: [bool; 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: [bool; 254] = modulus_le_bits().as_array();\n assert(!p_plus_4_bits[2]);\n p_plus_4_bits[2] = true;\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: [bool; 254] = p_plus_4.to_le_bits();\n assert(p_plus_4_converted_bits[2]);\n p_plus_4_converted_bits[2] = false;\n assert_eq(p_plus_4_converted_bits, [false; 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 bits produces 254 false values\n let p_bits: [bool; 254] = 0.to_le_bits();\n assert_eq(p_bits, [false; 254]);\n }\n }\n}\n"
3329
3329
  },
3330
3330
  "171": {
3331
3331
  "function_locations": [
@@ -3343,19 +3343,19 @@
3343
3343
  },
3344
3344
  {
3345
3345
  "name": "<impl Packable for DelayedPublicMutableValues<T, INITIAL_DELAY>>::pack",
3346
- "start": 4557
3346
+ "start": 4565
3347
3347
  },
3348
3348
  {
3349
3349
  "name": "<impl Packable for DelayedPublicMutableValues<T, INITIAL_DELAY>>::unpack",
3350
- "start": 5958
3350
+ "start": 5966
3351
3351
  },
3352
3352
  {
3353
3353
  "name": "<impl Hash for DelayedPublicMutableValues<T, INITIAL_DELAY>>::hash",
3354
- "start": 6257
3354
+ "start": 6265
3355
3355
  }
3356
3356
  ],
3357
3357
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/delayed_public_mutable/delayed_public_mutable_values.nr",
3358
- "source": "use crate::{\n delayed_public_mutable::{\n scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange,\n },\n hash::poseidon2_hash,\n traits::{Hash, Packable},\n utils::arrays,\n};\nuse std::meta::derive;\n\nmod test;\n\n/// DelayedPublicMutableValues is just a wrapper around ScheduledValueChange and ScheduledDelayChange that then allows us\n/// to wrap both of these values in WithHash. WithHash allows for efficient read of values in private.\n///\n/// Note that the WithHash optimization does not work in public (due to there being no unconstrained). But we also want\n/// to be able to read the values efficiently in public and we want to be able to read each value separately. Reading\n/// the values separately is tricky because ScheduledValueChange and ScheduledDelayChange are packed together (sdc and\n/// svc.timestamp_of_change are stored in the same slot). For that reason we expose `unpack_value_change` and\n/// `unpack_delay_change` functions that can be used to extract the values from the packed representation. This\n/// is \"hacky\" but there is no way around it.\n#[derive(Eq)]\npub struct DelayedPublicMutableValues<T, let INITIAL_DELAY: u64> {\n pub svc: ScheduledValueChange<T>,\n pub sdc: ScheduledDelayChange<INITIAL_DELAY>,\n}\n\nimpl<T, let INITIAL_DELAY: u64> DelayedPublicMutableValues<T, INITIAL_DELAY> {\n pub fn new(svc: ScheduledValueChange<T>, sdc: ScheduledDelayChange<INITIAL_DELAY>) -> Self {\n DelayedPublicMutableValues { svc, sdc }\n }\n}\n\n/// Extracts a ScheduledValueChange struct from the packed representation of the full DelayedPublicMutable.\n/// TODO: impl the packable trait for ScheduledValueChange.\npub fn unpack_value_change<T, let M: u32>(packed: [Field; 2 * M + 1]) -> ScheduledValueChange<T>\nwhere\n T: Packable<N = M>,\n{\n let svc_pre_packed = arrays::subarray(packed, 1);\n let svc_post_packed = arrays::subarray(packed, M + 1);\n\n // We first cast to u32 as the timestamp_of_change is packed into the same field as the delay change and it\n // occupies the first 32 bits of the field.\n let timestamp_of_change = (packed[0] as u32) as u64;\n ScheduledValueChange::new(\n T::unpack(svc_pre_packed),\n T::unpack(svc_post_packed),\n timestamp_of_change,\n )\n}\n\n/// Extracts a ScheduledDelayChange struct from 0th field of the packed representation of the full DelayedPublicMutable.\n/// This function expects to be called with just the first field of the packed representation, which contains sdc\n/// and svc timestamp_of_change. We'll discard the svc component.\npub fn unpack_delay_change<let INITIAL_DELAY: u64>(\n packed: Field,\n) -> ScheduledDelayChange<INITIAL_DELAY> {\n // This function expects to be called with just the first field of the packed representation, which contains sdc\n // and svc timestamp_of_change. We'll discard the svc component.\n let svc_timestamp_of_change = packed as u32;\n\n let mut tmp = (packed - svc_timestamp_of_change as Field) / TWO_POW_32;\n let sdc_timestamp_of_change = tmp as u32;\n\n tmp = (tmp - sdc_timestamp_of_change as Field) / TWO_POW_32;\n let sdc_post_is_some = (tmp as u1) != 0;\n\n tmp = (tmp - sdc_post_is_some as Field) / TWO_POW_8;\n let sdc_post_inner = tmp as u32;\n\n tmp = (tmp - sdc_post_inner as Field) / TWO_POW_32;\n let sdc_pre_is_some = (tmp as u1) != 0;\n\n tmp = (tmp - sdc_pre_is_some as Field) / TWO_POW_8;\n let sdc_pre_inner = tmp as u32;\n\n // Note that below we cast the values to u64 as that is the default type of timestamp in the system. Us packing\n // the values as u32 is a tech debt that is not worth tackling.\n ScheduledDelayChange {\n pre: if sdc_pre_is_some {\n Option::some(sdc_pre_inner as u64)\n } else {\n Option::none()\n },\n post: if sdc_post_is_some {\n Option::some(sdc_post_inner as u64)\n } else {\n Option::none()\n },\n timestamp_of_change: sdc_timestamp_of_change as u64,\n }\n}\n\n// Q: do these evaluate at comptime or runtime?\nglobal TWO_POW_32: Field = 2.pow_32(32);\nglobal TWO_POW_8: Field = 2.pow_32(8);\n\n// We pack to `2 * N + 1` fields because ScheduledValueChange contains T twice (hence `2 * N`) and we need one extra\n// field to store ScheduledDelayChange and the timestamp_of_change of ScheduledValueChange.\nimpl<T, let INITIAL_DELAY: u64> Packable for DelayedPublicMutableValues<T, INITIAL_DELAY>\nwhere\n T: Packable,\n{\n let N: u32 = 2 * <T as Packable>::N + 1;\n\n fn pack(self) -> [Field; Self::N] {\n let mut result = [0; Self::N];\n\n // We pack sdc.pre, sdc.post, sdc.timestamp_of_change and svc.timestamp_of_change into a single field as follows:\n // [ sdc.pre_inner: u32 | sdc.pre_is_some: u8 | sdc.post_inner: u32 | sdc.post_is_some: u8 | sdc.timestamp_of_change: u32 | svc.timestamp_of_change: u32 ]\n // Note that the code below no longer works after 2106 as by that time the timestamp will overflow u32. This is a tech debt that is not worth tackling.\n result[0] = self.svc.timestamp_of_change as Field\n + ((self.sdc.timestamp_of_change as Field) * 2.pow_32(32))\n + ((self.sdc.post.is_some() as Field) * 2.pow_32(64))\n + ((self.sdc.post.unwrap_unchecked() as Field) * 2.pow_32(72))\n + ((self.sdc.pre.is_some() as Field) * 2.pow_32(104))\n + ((self.sdc.pre.unwrap_unchecked() as Field) * 2.pow_32(112));\n\n // Pack the pre and post values from ScheduledValueChange\n let svc_pre_packed = self.svc.pre.pack();\n let svc_post_packed = self.svc.post.pack();\n for i in 0..<T as Packable>::N {\n result[i + 1] = svc_pre_packed[i];\n result[i + 1 + <T as Packable>::N] = svc_post_packed[i];\n }\n result\n }\n\n // Note: inefficient if all you want to unpack is the svc; use unpack_value_change instead.\n fn unpack(fields: [Field; Self::N]) -> Self {\n let svc = unpack_value_change::<T, _>(fields);\n let sdc = unpack_delay_change::<INITIAL_DELAY>(fields[0]);\n Self::new(svc, sdc)\n }\n}\n\nimpl<T, let INITIAL_DELAY: u64> Hash for DelayedPublicMutableValues<T, INITIAL_DELAY>\nwhere\n T: Packable,\n{\n fn hash(self) -> Field {\n poseidon2_hash(self.pack())\n }\n}\n"
3358
+ "source": "use crate::{\n delayed_public_mutable::{\n scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange,\n },\n hash::poseidon2_hash,\n traits::{Hash, Packable},\n utils::arrays,\n};\nuse std::meta::derive;\n\nmod test;\n\n/// DelayedPublicMutableValues is just a wrapper around ScheduledValueChange and ScheduledDelayChange that then allows us\n/// to wrap both of these values in WithHash. WithHash allows for efficient read of values in private.\n///\n/// Note that the WithHash optimization does not work in public (due to there being no unconstrained). But we also want\n/// to be able to read the values efficiently in public and we want to be able to read each value separately. Reading\n/// the values separately is tricky because ScheduledValueChange and ScheduledDelayChange are packed together (sdc and\n/// svc.timestamp_of_change are stored in the same slot). For that reason we expose `unpack_value_change` and\n/// `unpack_delay_change` functions that can be used to extract the values from the packed representation. This\n/// is \"hacky\" but there is no way around it.\n#[derive(Eq)]\npub struct DelayedPublicMutableValues<T, let INITIAL_DELAY: u64> {\n pub svc: ScheduledValueChange<T>,\n pub sdc: ScheduledDelayChange<INITIAL_DELAY>,\n}\n\nimpl<T, let INITIAL_DELAY: u64> DelayedPublicMutableValues<T, INITIAL_DELAY> {\n pub fn new(svc: ScheduledValueChange<T>, sdc: ScheduledDelayChange<INITIAL_DELAY>) -> Self {\n DelayedPublicMutableValues { svc, sdc }\n }\n}\n\n/// Extracts a ScheduledValueChange struct from the packed representation of the full DelayedPublicMutable.\n/// TODO: impl the packable trait for ScheduledValueChange.\npub fn unpack_value_change<T, let M: u32>(packed: [Field; 2 * M + 1]) -> ScheduledValueChange<T>\nwhere\n T: Packable<N = M>,\n{\n let svc_pre_packed = arrays::subarray(packed, 1);\n let svc_post_packed = arrays::subarray(packed, M + 1);\n\n // We first cast to u32 as the timestamp_of_change is packed into the same field as the delay change and it\n // occupies the first 32 bits of the field.\n let timestamp_of_change = (packed[0] as u32) as u64;\n ScheduledValueChange::new(\n T::unpack(svc_pre_packed),\n T::unpack(svc_post_packed),\n timestamp_of_change,\n )\n}\n\n/// Extracts a ScheduledDelayChange struct from 0th field of the packed representation of the full DelayedPublicMutable.\n/// This function expects to be called with just the first field of the packed representation, which contains sdc\n/// and svc timestamp_of_change. We'll discard the svc component.\npub fn unpack_delay_change<let INITIAL_DELAY: u64>(\n packed: Field,\n) -> ScheduledDelayChange<INITIAL_DELAY> {\n // This function expects to be called with just the first field of the packed representation, which contains sdc\n // and svc timestamp_of_change. We'll discard the svc component.\n let svc_timestamp_of_change = packed as u32;\n\n let mut tmp = (packed - svc_timestamp_of_change as Field) / TWO_POW_32;\n let sdc_timestamp_of_change = tmp as u32;\n\n tmp = (tmp - sdc_timestamp_of_change as Field) / TWO_POW_32;\n let sdc_post_is_some = (tmp as u8) % 2 != 0;\n\n tmp = (tmp - sdc_post_is_some as Field) / TWO_POW_8;\n let sdc_post_inner = tmp as u32;\n\n tmp = (tmp - sdc_post_inner as Field) / TWO_POW_32;\n let sdc_pre_is_some = (tmp as u8) % 2 != 0;\n\n tmp = (tmp - sdc_pre_is_some as Field) / TWO_POW_8;\n let sdc_pre_inner = tmp as u32;\n\n // Note that below we cast the values to u64 as that is the default type of timestamp in the system. Us packing\n // the values as u32 is a tech debt that is not worth tackling.\n ScheduledDelayChange {\n pre: if sdc_pre_is_some {\n Option::some(sdc_pre_inner as u64)\n } else {\n Option::none()\n },\n post: if sdc_post_is_some {\n Option::some(sdc_post_inner as u64)\n } else {\n Option::none()\n },\n timestamp_of_change: sdc_timestamp_of_change as u64,\n }\n}\n\n// Q: do these evaluate at comptime or runtime?\nglobal TWO_POW_32: Field = 2.pow_32(32);\nglobal TWO_POW_8: Field = 2.pow_32(8);\n\n// We pack to `2 * N + 1` fields because ScheduledValueChange contains T twice (hence `2 * N`) and we need one extra\n// field to store ScheduledDelayChange and the timestamp_of_change of ScheduledValueChange.\nimpl<T, let INITIAL_DELAY: u64> Packable for DelayedPublicMutableValues<T, INITIAL_DELAY>\nwhere\n T: Packable,\n{\n let N: u32 = 2 * <T as Packable>::N + 1;\n\n fn pack(self) -> [Field; Self::N] {\n let mut result = [0; Self::N];\n\n // We pack sdc.pre, sdc.post, sdc.timestamp_of_change and svc.timestamp_of_change into a single field as follows:\n // [ sdc.pre_inner: u32 | sdc.pre_is_some: u8 | sdc.post_inner: u32 | sdc.post_is_some: u8 | sdc.timestamp_of_change: u32 | svc.timestamp_of_change: u32 ]\n // Note that the code below no longer works after 2106 as by that time the timestamp will overflow u32. This is a tech debt that is not worth tackling.\n result[0] = self.svc.timestamp_of_change as Field\n + ((self.sdc.timestamp_of_change as Field) * 2.pow_32(32))\n + ((self.sdc.post.is_some() as Field) * 2.pow_32(64))\n + ((self.sdc.post.unwrap_unchecked() as Field) * 2.pow_32(72))\n + ((self.sdc.pre.is_some() as Field) * 2.pow_32(104))\n + ((self.sdc.pre.unwrap_unchecked() as Field) * 2.pow_32(112));\n\n // Pack the pre and post values from ScheduledValueChange\n let svc_pre_packed = self.svc.pre.pack();\n let svc_post_packed = self.svc.post.pack();\n for i in 0..<T as Packable>::N {\n result[i + 1] = svc_pre_packed[i];\n result[i + 1 + <T as Packable>::N] = svc_post_packed[i];\n }\n result\n }\n\n // Note: inefficient if all you want to unpack is the svc; use unpack_value_change instead.\n fn unpack(fields: [Field; Self::N]) -> Self {\n let svc = unpack_value_change::<T, _>(fields);\n let sdc = unpack_delay_change::<INITIAL_DELAY>(fields[0]);\n Self::new(svc, sdc)\n }\n}\n\nimpl<T, let INITIAL_DELAY: u64> Hash for DelayedPublicMutableValues<T, INITIAL_DELAY>\nwhere\n T: Packable,\n{\n fn hash(self) -> Field {\n poseidon2_hash(self.pack())\n }\n}\n"
3359
3359
  },
3360
3360
  "174": {
3361
3361
  "function_locations": [
@@ -3587,131 +3587,123 @@
3587
3587
  },
3588
3588
  {
3589
3589
  "name": "pedersen_hash",
3590
- "start": 2460
3590
+ "start": 2380
3591
3591
  },
3592
3592
  {
3593
3593
  "name": "pedersen_hash_with_separator",
3594
- "start": 2617
3594
+ "start": 2537
3595
3595
  },
3596
3596
  {
3597
3597
  "name": "derive_generators",
3598
- "start": 3591
3598
+ "start": 3531
3599
3599
  },
3600
3600
  {
3601
3601
  "name": "__derive_generators",
3602
- "start": 3950
3603
- },
3604
- {
3605
- "name": "from_field_unsafe",
3606
- "start": 4265
3602
+ "start": 3890
3607
3603
  },
3608
3604
  {
3609
3605
  "name": "poseidon2_permutation",
3610
- "start": 4922
3606
+ "start": 3968
3611
3607
  },
3612
3608
  {
3613
3609
  "name": "poseidon2_permutation_internal",
3614
- "start": 5318
3610
+ "start": 4324
3615
3611
  },
3616
3612
  {
3617
3613
  "name": "poseidon2_config_state_size",
3618
- "start": 5411
3614
+ "start": 4417
3619
3615
  },
3620
3616
  {
3621
3617
  "name": "derive_hash",
3622
- "start": 5722
3618
+ "start": 4728
3623
3619
  },
3624
3620
  {
3625
3621
  "name": "<impl BuildHasher for BuildHasherDefault<H>>::build_hasher",
3626
- "start": 6693
3622
+ "start": 5953
3627
3623
  },
3628
3624
  {
3629
3625
  "name": "<impl Default for BuildHasherDefault<H>>::default",
3630
- "start": 6825
3626
+ "start": 6085
3631
3627
  },
3632
3628
  {
3633
3629
  "name": "<impl Hash for Field>::hash",
3634
- "start": 6957
3635
- },
3636
- {
3637
- "name": "<impl Hash for u1>::hash",
3638
- "start": 7087
3630
+ "start": 6217
3639
3631
  },
3640
3632
  {
3641
3633
  "name": "<impl Hash for u8>::hash",
3642
- "start": 7226
3634
+ "start": 6347
3643
3635
  },
3644
3636
  {
3645
3637
  "name": "<impl Hash for u16>::hash",
3646
- "start": 7366
3638
+ "start": 6487
3647
3639
  },
3648
3640
  {
3649
3641
  "name": "<impl Hash for u32>::hash",
3650
- "start": 7506
3642
+ "start": 6627
3651
3643
  },
3652
3644
  {
3653
3645
  "name": "<impl Hash for u64>::hash",
3654
- "start": 7646
3646
+ "start": 6767
3655
3647
  },
3656
3648
  {
3657
3649
  "name": "<impl Hash for u128>::hash",
3658
- "start": 7787
3650
+ "start": 6908
3659
3651
  },
3660
3652
  {
3661
3653
  "name": "<impl Hash for i8>::hash",
3662
- "start": 7926
3654
+ "start": 7047
3663
3655
  },
3664
3656
  {
3665
3657
  "name": "<impl Hash for i16>::hash",
3666
- "start": 8072
3658
+ "start": 7193
3667
3659
  },
3668
3660
  {
3669
3661
  "name": "<impl Hash for i32>::hash",
3670
- "start": 8219
3662
+ "start": 7340
3671
3663
  },
3672
3664
  {
3673
3665
  "name": "<impl Hash for i64>::hash",
3674
- "start": 8366
3666
+ "start": 7487
3675
3667
  },
3676
3668
  {
3677
3669
  "name": "<impl Hash for bool>::hash",
3678
- "start": 8514
3670
+ "start": 7635
3679
3671
  },
3680
3672
  {
3681
3673
  "name": "<impl Hash for ()>::hash",
3682
- "start": 8661
3674
+ "start": 7782
3683
3675
  },
3684
3676
  {
3685
3677
  "name": "<impl Hash for [T; N]>::hash",
3686
- "start": 8793
3678
+ "start": 7914
3687
3679
  },
3688
3680
  {
3689
3681
  "name": "<impl Hash for [T]>::hash",
3690
- "start": 8982
3682
+ "start": 8103
3691
3683
  },
3692
3684
  {
3693
3685
  "name": "<impl Hash for (A, B)>::hash",
3694
- "start": 9222
3686
+ "start": 8343
3695
3687
  },
3696
3688
  {
3697
3689
  "name": "<impl Hash for (A, B, C)>::hash",
3698
- "start": 9438
3690
+ "start": 8559
3699
3691
  },
3700
3692
  {
3701
3693
  "name": "<impl Hash for (A, B, C, D)>::hash",
3702
- "start": 9701
3694
+ "start": 8822
3703
3695
  },
3704
3696
  {
3705
3697
  "name": "<impl Hash for (A, B, C, D, E)>::hash",
3706
- "start": 10011
3698
+ "start": 9132
3707
3699
  },
3708
3700
  {
3709
3701
  "name": "assert_pedersen",
3710
- "start": 10407
3702
+ "start": 9528
3711
3703
  }
3712
3704
  ],
3713
3705
  "path": "std/hash/mod.nr",
3714
- "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;\nuse crate::static_assert;\n\n/// The size of the state accepted by the backend in `poseidon2_permutation`.\nglobal POSEIDON2_CONFIG_STATE_SIZE: u32 = poseidon2_config_state_size();\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<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(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<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(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<let N: u32>(\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<let N: u32>(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<let N: u32>(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 crate::assert_constant(separator);\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)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n crate::assert_constant(starting_index);\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\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 // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n\n static_assert(\n N == POSEIDON2_CONFIG_STATE_SIZE,\n f\"the input length must equal the state size in the Poseidon2 config; expected {POSEIDON2_CONFIG_STATE_SIZE}, got {N}\",\n );\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n#[foreign(poseidon2_config_state_size)]\ncomptime fn poseidon2_config_state_size() -> u32 {}\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<H>(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<H>(_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<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\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<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(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<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(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<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(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<A, B, C, D, E> 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<H>(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"
3706
+ "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;\nuse crate::static_assert;\n\n/// The size of the state accepted by the backend in `poseidon2_permutation`.\nglobal POSEIDON2_CONFIG_STATE_SIZE: u32 = poseidon2_config_state_size();\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<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(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<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(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<let N: u32>(\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 points[i] = EmbeddedCurveScalar::from_field(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<let N: u32>(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<let N: u32>(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 crate::assert_constant(separator);\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] = EmbeddedCurveScalar::from_field(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<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n crate::assert_constant(starting_index);\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N]) -> [Field; N] {\n static_assert(\n N == POSEIDON2_CONFIG_STATE_SIZE,\n f\"the input length must equal the state size in the Poseidon2 config; expected {POSEIDON2_CONFIG_STATE_SIZE}, got {N}\",\n );\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n#[foreign(poseidon2_config_state_size)]\ncomptime fn poseidon2_config_state_size() -> u32 {}\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<H>(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<H>(_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 /// Returns the hash value without consuming the hasher.\n /// Override this for more efficient implementations that avoid copying.\n /// TODO: deprecate finish() and replace it\n fn finish_ref(&self) -> Field {\n (*self).finish()\n }\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<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\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<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(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<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(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<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(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<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(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<A, B, C, D, E> 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<H>(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 },\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 },\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 },\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 },\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 },\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 },\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 },\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 },\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 },\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 },\n );\n}\n"
3715
3707
  },
3716
3708
  "181": {
3717
3709
  "function_locations": [
@@ -3789,107 +3781,179 @@
3789
3781
  },
3790
3782
  "199": {
3791
3783
  "function_locations": [
3784
+ {
3785
+ "name": "Point::generator",
3786
+ "start": 918
3787
+ },
3788
+ {
3789
+ "name": "Point::point_at_infinity",
3790
+ "start": 1068
3791
+ },
3792
+ {
3793
+ "name": "Point::double",
3794
+ "start": 1157
3795
+ },
3796
+ {
3797
+ "name": "Point::to_embedded",
3798
+ "start": 1260
3799
+ },
3800
+ {
3801
+ "name": "<impl From<EmbeddedCurvePoint> for Point>::from",
3802
+ "start": 1408
3803
+ },
3804
+ {
3805
+ "name": "<impl std::ops::Add for Point>::add",
3806
+ "start": 1553
3807
+ },
3808
+ {
3809
+ "name": "<impl std::ops::Sub for Point>::sub",
3810
+ "start": 1693
3811
+ },
3812
+ {
3813
+ "name": "<impl std::ops::Neg for Point>::neg",
3814
+ "start": 1819
3815
+ },
3816
+ {
3817
+ "name": "<impl Eq for Point>::eq",
3818
+ "start": 1959
3819
+ },
3792
3820
  {
3793
3821
  "name": "<impl Hash for Point>::hash",
3794
- "start": 239
3822
+ "start": 2111
3795
3823
  },
3796
3824
  {
3797
3825
  "name": "<impl Empty for Point>::empty",
3798
- "start": 509
3826
+ "start": 2381
3827
+ },
3828
+ {
3829
+ "name": "<impl Serialize for Point>::serialize",
3830
+ "start": 2543
3831
+ },
3832
+ {
3833
+ "name": "<impl Serialize for Point>::stream_serialize",
3834
+ "start": 2670
3835
+ },
3836
+ {
3837
+ "name": "<impl Deserialize for Point>::deserialize",
3838
+ "start": 2904
3839
+ },
3840
+ {
3841
+ "name": "<impl Deserialize for Point>::stream_deserialize",
3842
+ "start": 3078
3799
3843
  },
3800
3844
  {
3801
3845
  "name": "validate_on_curve",
3802
- "start": 604
3846
+ "start": 3210
3803
3847
  },
3804
3848
  {
3805
3849
  "name": "<impl Packable for Point>::pack",
3806
- "start": 1155
3850
+ "start": 3761
3807
3851
  },
3808
3852
  {
3809
3853
  "name": "<impl Packable for Point>::unpack",
3810
- "start": 1237
3854
+ "start": 3843
3811
3855
  },
3812
3856
  {
3813
3857
  "name": "tests::test_validate_on_curve_generator",
3814
- "start": 1459
3858
+ "start": 4012
3815
3859
  },
3816
3860
  {
3817
3861
  "name": "tests::test_validate_on_curve_infinity",
3818
- "start": 1671
3862
+ "start": 4224
3819
3863
  },
3820
3864
  {
3821
3865
  "name": "tests::test_validate_on_curve_invalid_point",
3822
- "start": 1953
3866
+ "start": 4506
3823
3867
  },
3824
3868
  {
3825
3869
  "name": "tests::test_validate_on_curve_infinity_non_canonical_x",
3826
- "start": 2276
3870
+ "start": 4829
3827
3871
  },
3828
3872
  {
3829
3873
  "name": "tests::test_validate_on_curve_infinity_non_canonical_y",
3830
- "start": 2622
3874
+ "start": 5175
3831
3875
  }
3832
3876
  ],
3833
3877
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/point.nr",
3834
- "source": "pub use std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}};\n\npub global POINT_LENGTH: u32 = 3;\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\npub fn validate_on_curve(p: Point) {\n // y^2 == x^3 - 17\n let x = p.x;\n let y = p.y;\n if p.is_infinite {\n // Assert the canonical representation of infinity\n assert_eq(x, 0, \"Point at infinity should have canonical representation (0 0)\");\n assert_eq(y, 0, \"Point at infinity should have canonical representation (0 0)\");\n } else {\n assert_eq(y * y, x * x * x - 17, \"Point not on curve\");\n }\n}\n\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n let N: u32 = POINT_LENGTH;\n\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n\nmod tests {\n use super::validate_on_curve;\n use std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\n #[test]\n unconstrained fn test_validate_on_curve_generator() {\n // The generator point should be on the curve\n let generator = Point::generator();\n validate_on_curve(generator);\n }\n\n #[test]\n unconstrained fn test_validate_on_curve_infinity() {\n // Canonical infinite point (x=0, y=0) should pass\n let infinity = Point { x: 0, y: 0, is_infinite: true };\n validate_on_curve(infinity);\n }\n\n #[test(should_fail_with = \"Point not on curve\")]\n unconstrained fn test_validate_on_curve_invalid_point() {\n // A point not on the curve should fail\n let invalid = Point { x: 1, y: 1, is_infinite: false };\n validate_on_curve(invalid);\n }\n\n #[test(should_fail_with = \"Point at infinity should have canonical representation (0 0)\")]\n unconstrained fn test_validate_on_curve_infinity_non_canonical_x() {\n // Infinite point with non-zero x should fail\n let invalid_infinity = Point { x: 1, y: 0, is_infinite: true };\n validate_on_curve(invalid_infinity);\n }\n\n #[test(should_fail_with = \"Point at infinity should have canonical representation (0 0)\")]\n unconstrained fn test_validate_on_curve_infinity_non_canonical_y() {\n // Infinite point with non-zero y should fail\n let invalid_infinity = Point { x: 0, y: 1, is_infinite: true };\n validate_on_curve(invalid_infinity);\n }\n}\n"
3878
+ "source": "use crate::{\n hash::poseidon2_hash,\n traits::{Deserialize, Empty, Hash, Packable, Serialize},\n utils::{reader::Reader, writer::Writer},\n};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\n\npub global POINT_LENGTH: u32 = 3;\n\n// TODO(F-553): This custom `Point` struct is a temporary workaround. A newer version of Noir dropped the `is_infinite`\n// field from `EmbeddedCurvePoint` and changed its serialization from 3 fields to 2. To preserve backwards compatibility\n// of our onchain serialization format we re-introduced our own `Point` that wraps `EmbeddedCurvePoint` and keeps the\n// old 3-field layout. Once we're ready to take the breaking change (e.g. alongside the v5 oracle changes), delete this\n// struct, use `EmbeddedCurvePoint` directly and reduce `POINT_LENGTH` to 2.\npub struct Point {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl Point {\n pub fn generator() -> Self {\n let g = EmbeddedCurvePoint::generator();\n Point { x: g.x, y: g.y, is_infinite: false }\n }\n\n pub fn point_at_infinity() -> Self {\n Point { x: 0, y: 0, is_infinite: true }\n }\n\n pub fn double(self) -> Self {\n self.to_embedded().double().into()\n }\n\n pub fn to_embedded(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: self.y }\n }\n}\n\nimpl From<EmbeddedCurvePoint> for Point {\n fn from(p: EmbeddedCurvePoint) -> Self {\n Point { x: p.x, y: p.y, is_infinite: p.is_infinite() }\n }\n}\n\nimpl std::ops::Add for Point {\n fn add(self, other: Point) -> Point {\n (self.to_embedded() + other.to_embedded()).into()\n }\n}\n\nimpl std::ops::Sub for Point {\n fn sub(self, other: Point) -> Point {\n (self.to_embedded() - other.to_embedded()).into()\n }\n}\n\nimpl std::ops::Neg for Point {\n fn neg(self) -> Point {\n Point { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for Point {\n fn eq(self, other: Point) -> bool {\n (self.x == other.x) & (self.y == other.y) & (self.is_infinite == other.is_infinite)\n }\n}\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\nimpl Serialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y, self.is_infinite as Field]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n writer.write(self.is_infinite as Field);\n }\n}\n\nimpl Deserialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Point { x: fields[0], y: fields[1], is_infinite: fields[2] != 0 }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Point { x: reader.read(), y: reader.read(), is_infinite: reader.read_bool() }\n }\n}\n\npub fn validate_on_curve(p: Point) {\n // y^2 == x^3 - 17\n let x = p.x;\n let y = p.y;\n if p.is_infinite {\n // Assert the canonical representation of infinity\n assert_eq(x, 0, \"Point at infinity should have canonical representation (0 0)\");\n assert_eq(y, 0, \"Point at infinity should have canonical representation (0 0)\");\n } else {\n assert_eq(y * y, x * x * x - 17, \"Point not on curve\");\n }\n}\n\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n let N: u32 = POINT_LENGTH;\n\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n\nmod tests {\n use super::{Point, validate_on_curve};\n\n #[test]\n unconstrained fn test_validate_on_curve_generator() {\n // The generator point should be on the curve\n let generator = Point::generator();\n validate_on_curve(generator);\n }\n\n #[test]\n unconstrained fn test_validate_on_curve_infinity() {\n // Canonical infinite point (x=0, y=0) should pass\n let infinity = Point { x: 0, y: 0, is_infinite: true };\n validate_on_curve(infinity);\n }\n\n #[test(should_fail_with = \"Point not on curve\")]\n unconstrained fn test_validate_on_curve_invalid_point() {\n // A point not on the curve should fail\n let invalid = Point { x: 1, y: 1, is_infinite: false };\n validate_on_curve(invalid);\n }\n\n #[test(should_fail_with = \"Point at infinity should have canonical representation (0 0)\")]\n unconstrained fn test_validate_on_curve_infinity_non_canonical_x() {\n // Infinite point with non-zero x should fail\n let invalid_infinity = Point { x: 1, y: 0, is_infinite: true };\n validate_on_curve(invalid_infinity);\n }\n\n #[test(should_fail_with = \"Point at infinity should have canonical representation (0 0)\")]\n unconstrained fn test_validate_on_curve_infinity_non_canonical_y() {\n // Infinite point with non-zero y should fail\n let invalid_infinity = Point { x: 0, y: 1, is_infinite: true };\n validate_on_curve(invalid_infinity);\n }\n}\n"
3835
3879
  },
3836
3880
  "207": {
3837
3881
  "function_locations": [
3838
3882
  {
3839
3883
  "name": "<impl ToPoint for NpkM>::to_point",
3840
- "start": 679
3884
+ "start": 646
3841
3885
  },
3842
3886
  {
3843
3887
  "name": "<impl Hash for NpkM>::hash",
3844
- "start": 849
3888
+ "start": 816
3845
3889
  },
3846
3890
  {
3847
3891
  "name": "<impl ToPoint for IvpkM>::to_point",
3848
- "start": 1024
3892
+ "start": 991
3849
3893
  },
3850
3894
  {
3851
3895
  "name": "<impl Hash for OvpkM>::hash",
3852
- "start": 1185
3896
+ "start": 1152
3853
3897
  },
3854
3898
  {
3855
3899
  "name": "<impl ToPoint for OvpkM>::to_point",
3856
- "start": 1278
3900
+ "start": 1245
3857
3901
  },
3858
3902
  {
3859
3903
  "name": "<impl ToPoint for TpkM>::to_point",
3860
- "start": 1444
3904
+ "start": 1411
3861
3905
  },
3862
3906
  {
3863
3907
  "name": "<impl Default for PublicKeys>::default",
3864
- "start": 1682
3908
+ "start": 1649
3865
3909
  },
3866
3910
  {
3867
3911
  "name": "PublicKeys::hash",
3868
- "start": 2326
3912
+ "start": 2293
3869
3913
  },
3870
3914
  {
3871
3915
  "name": "PublicKeys::validate_on_curve",
3872
- "start": 2525
3916
+ "start": 2492
3917
+ },
3918
+ {
3919
+ "name": "PublicKeys::validate_non_infinity",
3920
+ "start": 2722
3873
3921
  },
3874
3922
  {
3875
3923
  "name": "<impl ToPoint for AddressPoint>::to_point",
3876
- "start": 2832
3924
+ "start": 3207
3877
3925
  },
3878
3926
  {
3879
3927
  "name": "test::compute_public_keys_hash",
3880
- "start": 3152
3928
+ "start": 3517
3929
+ },
3930
+ {
3931
+ "name": "test::test_validate_on_curve",
3932
+ "start": 4231
3933
+ },
3934
+ {
3935
+ "name": "test::test_validate_not_on_curve",
3936
+ "start": 4690
3937
+ },
3938
+ {
3939
+ "name": "test::test_validate_non_infinity",
3940
+ "start": 5151
3941
+ },
3942
+ {
3943
+ "name": "test::test_validate_infinity",
3944
+ "start": 5621
3881
3945
  },
3882
3946
  {
3883
3947
  "name": "test::compute_default_hash",
3884
- "start": 3864
3948
+ "start": 6015
3885
3949
  },
3886
3950
  {
3887
3951
  "name": "test::serde",
3888
- "start": 4242
3952
+ "start": 6393
3889
3953
  }
3890
3954
  ],
3891
3955
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr",
3892
- "source": "use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, DOM_SEP__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n point::validate_on_curve,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse std::{default::Default, meta::derive};\nuse std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n DOM_SEP__PUBLIC_KEYS_HASH as Field,\n ))\n }\n\n pub fn validate_on_curve(self) {\n validate_on_curve(self.npk_m.inner);\n validate_on_curve(self.ivpk_m.inner);\n validate_on_curve(self.ovpk_m.inner);\n validate_on_curve(self.tpk_m.inner);\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nmod test {\n use crate::{\n point::POINT_LENGTH,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n traits::{Deserialize, Serialize},\n };\n use std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\n #[test]\n unconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n\n // The following value was generated by `public_keys.test.ts`.\n let expected_public_keys_hash =\n 0x056998309f6c119e4d753e404f94fef859dddfa530a9379634ceb0854b29bf7a;\n\n assert(actual.to_field() == expected_public_keys_hash);\n }\n\n #[test]\n unconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n\n // The following value was generated by `public_keys.test.ts`.\n let test_data_default_hash =\n 0x023547e676dba19784188825b901a0e70d8ad978300d21d6185a54281b734da0;\n\n assert(actual.to_field() == test_data_default_hash);\n }\n\n #[test]\n unconstrained fn serde() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n // We use the PUBLIC_KEYS_LENGTH constant to ensure that there is a match between the derived trait\n let serialized: [Field; POINT_LENGTH * 4] = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys, deserialized);\n }\n}\n"
3956
+ "source": "use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, DOM_SEP__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n point::validate_on_curve,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse crate::point::Point;\nuse std::{default::Default, meta::derive};\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n DOM_SEP__PUBLIC_KEYS_HASH as Field,\n ))\n }\n\n pub fn validate_on_curve(self) {\n validate_on_curve(self.npk_m.inner);\n validate_on_curve(self.ivpk_m.inner);\n validate_on_curve(self.ovpk_m.inner);\n validate_on_curve(self.tpk_m.inner);\n }\n\n pub fn validate_non_infinity(self) {\n assert_eq(self.npk_m.inner.is_infinite, false, \"NpkM is the point at infinity\");\n assert_eq(self.ivpk_m.inner.is_infinite, false, \"IvpkM is the point at infinity\");\n assert_eq(self.ovpk_m.inner.is_infinite, false, \"OvpkM is the point at infinity\");\n assert_eq(self.tpk_m.inner.is_infinite, false, \"TpkM is the point at infinity\");\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nmod test {\n use crate::point::Point;\n use crate::{\n point::POINT_LENGTH,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n traits::{Deserialize, Serialize},\n };\n use std::ops::Neg;\n\n #[test]\n unconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n\n // The following value was generated by `public_keys.test.ts`.\n let expected_public_keys_hash =\n 0x056998309f6c119e4d753e404f94fef859dddfa530a9379634ceb0854b29bf7a;\n\n assert(actual.to_field() == expected_public_keys_hash);\n }\n\n #[test]\n unconstrained fn test_validate_on_curve() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point::generator() },\n ivpk_m: IvpkM { inner: Point::generator().double() },\n ovpk_m: OvpkM { inner: Point::generator().neg() },\n tpk_m: TpkM { inner: Point::generator() + Point::generator().double() },\n };\n\n keys.validate_on_curve();\n }\n\n #[test(should_fail_with = \"Point not on curve\")]\n unconstrained fn test_validate_not_on_curve() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n keys.validate_on_curve();\n }\n\n #[test]\n unconstrained fn test_validate_non_infinity() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point::generator() },\n ivpk_m: IvpkM { inner: Point::generator().double() },\n ovpk_m: OvpkM { inner: Point::generator().neg() },\n tpk_m: TpkM { inner: Point::generator() + Point::generator().double() },\n };\n\n keys.validate_non_infinity();\n }\n\n #[test(should_fail_with = \"TpkM is the point at infinity\")]\n unconstrained fn test_validate_infinity() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point::generator() },\n ivpk_m: IvpkM { inner: Point::generator().double() },\n ovpk_m: OvpkM { inner: Point::generator().neg() },\n tpk_m: TpkM { inner: Point::point_at_infinity() },\n };\n\n keys.validate_non_infinity();\n }\n\n #[test]\n unconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n\n // The following value was generated by `public_keys.test.ts`.\n let test_data_default_hash =\n 0x023547e676dba19784188825b901a0e70d8ad978300d21d6185a54281b734da0;\n\n assert(actual.to_field() == test_data_default_hash);\n }\n\n #[test]\n unconstrained fn serde() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n // We use the PUBLIC_KEYS_LENGTH constant to ensure that there is a match between the derived trait\n let serialized: [Field; POINT_LENGTH * 4] = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys, deserialized);\n }\n}\n"
3893
3957
  },
3894
3958
  "212": {
3895
3959
  "function_locations": [
@@ -3917,115 +3981,115 @@
3917
3981
  },
3918
3982
  {
3919
3983
  "name": "<impl Packable for u8>::pack",
3920
- "start": 763
3984
+ "start": 767
3921
3985
  },
3922
3986
  {
3923
3987
  "name": "<impl Packable for u8>::unpack",
3924
- "start": 865
3988
+ "start": 869
3925
3989
  },
3926
3990
  {
3927
3991
  "name": "<impl Packable for u16>::pack",
3928
- "start": 1017
3992
+ "start": 1021
3929
3993
  },
3930
3994
  {
3931
3995
  "name": "<impl Packable for u16>::unpack",
3932
- "start": 1119
3996
+ "start": 1123
3933
3997
  },
3934
3998
  {
3935
3999
  "name": "<impl Packable for u32>::pack",
3936
- "start": 1272
4000
+ "start": 1276
3937
4001
  },
3938
4002
  {
3939
4003
  "name": "<impl Packable for u32>::unpack",
3940
- "start": 1374
4004
+ "start": 1378
3941
4005
  },
3942
4006
  {
3943
4007
  "name": "<impl Packable for u64>::pack",
3944
- "start": 1527
4008
+ "start": 1531
3945
4009
  },
3946
4010
  {
3947
4011
  "name": "<impl Packable for u64>::unpack",
3948
- "start": 1629
4012
+ "start": 1633
3949
4013
  },
3950
4014
  {
3951
4015
  "name": "<impl Packable for u128>::pack",
3952
- "start": 1784
4016
+ "start": 1788
3953
4017
  },
3954
4018
  {
3955
4019
  "name": "<impl Packable for u128>::unpack",
3956
- "start": 1886
4020
+ "start": 1890
3957
4021
  },
3958
4022
  {
3959
4023
  "name": "<impl Packable for Field>::pack",
3960
- "start": 2044
4024
+ "start": 2048
3961
4025
  },
3962
4026
  {
3963
4027
  "name": "<impl Packable for Field>::unpack",
3964
- "start": 2137
4028
+ "start": 2141
3965
4029
  },
3966
4030
  {
3967
4031
  "name": "<impl Packable for i8>::pack",
3968
- "start": 2281
4032
+ "start": 2285
3969
4033
  },
3970
4034
  {
3971
4035
  "name": "<impl Packable for i8>::unpack",
3972
- "start": 2389
4036
+ "start": 2393
3973
4037
  },
3974
4038
  {
3975
4039
  "name": "<impl Packable for i16>::pack",
3976
- "start": 2547
4040
+ "start": 2551
3977
4041
  },
3978
4042
  {
3979
4043
  "name": "<impl Packable for i16>::unpack",
3980
- "start": 2656
4044
+ "start": 2660
3981
4045
  },
3982
4046
  {
3983
4047
  "name": "<impl Packable for i32>::pack",
3984
- "start": 2816
4048
+ "start": 2820
3985
4049
  },
3986
4050
  {
3987
4051
  "name": "<impl Packable for i32>::unpack",
3988
- "start": 2925
4052
+ "start": 2929
3989
4053
  },
3990
4054
  {
3991
4055
  "name": "<impl Packable for i64>::pack",
3992
- "start": 3085
4056
+ "start": 3089
3993
4057
  },
3994
4058
  {
3995
4059
  "name": "<impl Packable for i64>::unpack",
3996
- "start": 3194
4060
+ "start": 3198
3997
4061
  },
3998
4062
  {
3999
4063
  "name": "<impl Packable for [T; M]>::pack",
4000
- "start": 3403
4064
+ "start": 3407
4001
4065
  },
4002
4066
  {
4003
4067
  "name": "<impl Packable for [T; M]>::unpack",
4004
- "start": 3765
4068
+ "start": 3769
4005
4069
  },
4006
4070
  {
4007
4071
  "name": "test_u16_packing",
4008
- "start": 4010
4072
+ "start": 4014
4009
4073
  },
4010
4074
  {
4011
4075
  "name": "test_i8_packing",
4012
- "start": 4106
4076
+ "start": 4110
4013
4077
  },
4014
4078
  {
4015
4079
  "name": "test_i16_packing",
4016
- "start": 4202
4080
+ "start": 4206
4017
4081
  },
4018
4082
  {
4019
4083
  "name": "test_i32_packing",
4020
- "start": 4300
4084
+ "start": 4304
4021
4085
  },
4022
4086
  {
4023
4087
  "name": "test_i64_packing",
4024
- "start": 4398
4088
+ "start": 4402
4025
4089
  }
4026
4090
  ],
4027
4091
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr",
4028
- "source": "use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n (fields[0] as u1) != 0\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * <T as Packable>::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..<T as Packable>::N {\n result[i * <T as Packable>::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::<T, <T as Packable>::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n"
4092
+ "source": "use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n (fields[0] as u8) % 2 != 0\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * <T as Packable>::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..<T as Packable>::N {\n result[i * <T as Packable>::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::<T, <T as Packable>::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n"
4029
4093
  },
4030
4094
  "239": {
4031
4095
  "function_locations": [
@@ -4043,31 +4107,31 @@
4043
4107
  },
4044
4108
  {
4045
4109
  "name": "Poseidon2::absorb",
4046
- "start": 926
4110
+ "start": 923
4047
4111
  },
4048
4112
  {
4049
4113
  "name": "Poseidon2::squeeze",
4050
- "start": 1456
4114
+ "start": 1453
4051
4115
  },
4052
4116
  {
4053
4117
  "name": "Poseidon2::hash_internal",
4054
- "start": 1817
4118
+ "start": 1814
4055
4119
  },
4056
4120
  {
4057
4121
  "name": "<impl Hasher for Poseidon2Hasher>::finish",
4058
- "start": 4117
4122
+ "start": 4105
4059
4123
  },
4060
4124
  {
4061
4125
  "name": "<impl Hasher for Poseidon2Hasher>::write",
4062
- "start": 4438
4126
+ "start": 4426
4063
4127
  },
4064
4128
  {
4065
4129
  "name": "<impl Default for Poseidon2Hasher>::default",
4066
- "start": 4561
4130
+ "start": 4549
4067
4131
  }
4068
4132
  ],
4069
- "path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.2.6/src/poseidon2.nr",
4070
- "source": "use std::default::Default;\nuse std::hash::Hasher;\n\nglobal RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash<let N: u32>(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0];\n self.state[1] += self.cache[1];\n self.state[2] += self.cache[2];\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state, 4);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1];\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state, 4);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state, 4);\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n"
4133
+ "path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.3.0/src/poseidon2.nr",
4134
+ "source": "use std::default::Default;\nuse std::hash::Hasher;\n\nglobal RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash<let N: u32>(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0];\n self.state[1] += self.cache[1];\n self.state[2] += self.cache[2];\n self.state = crate::poseidon2_permutation(self.state);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1];\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state);\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: @[] }\n }\n}\n"
4071
4135
  },
4072
4136
  "242": {
4073
4137
  "function_locations": [
@@ -4149,473 +4213,315 @@
4149
4213
  "function_locations": [
4150
4214
  {
4151
4215
  "name": "<impl Serialize for bool>::serialize",
4152
- "start": 728
4216
+ "start": 693
4153
4217
  },
4154
4218
  {
4155
4219
  "name": "<impl Serialize for bool>::stream_serialize",
4156
- "start": 949
4220
+ "start": 914
4157
4221
  },
4158
4222
  {
4159
4223
  "name": "<impl Deserialize for bool>::deserialize",
4160
- "start": 1117
4224
+ "start": 1082
4161
4225
  },
4162
4226
  {
4163
4227
  "name": "<impl Deserialize for bool>::stream_deserialize",
4164
- "start": 1363
4165
- },
4166
- {
4167
- "name": "<impl Serialize for u1>::serialize",
4168
- "start": 1505
4169
- },
4170
- {
4171
- "name": "<impl Serialize for u1>::stream_serialize",
4172
- "start": 1726
4173
- },
4174
- {
4175
- "name": "<impl Deserialize for u1>::deserialize",
4176
- "start": 1890
4177
- },
4178
- {
4179
- "name": "<impl Deserialize for u1>::stream_deserialize",
4180
- "start": 2136
4228
+ "start": 1328
4181
4229
  },
4182
4230
  {
4183
4231
  "name": "<impl Serialize for u8>::serialize",
4184
- "start": 2279
4232
+ "start": 1470
4185
4233
  },
4186
4234
  {
4187
4235
  "name": "<impl Serialize for u8>::stream_serialize",
4188
- "start": 2500
4236
+ "start": 1691
4189
4237
  },
4190
4238
  {
4191
4239
  "name": "<impl Deserialize for u8>::deserialize",
4192
- "start": 2664
4240
+ "start": 1855
4193
4241
  },
4194
4242
  {
4195
4243
  "name": "<impl Deserialize for u8>::stream_deserialize",
4196
- "start": 2910
4244
+ "start": 2101
4197
4245
  },
4198
4246
  {
4199
4247
  "name": "<impl Serialize for u16>::serialize",
4200
- "start": 3055
4248
+ "start": 2246
4201
4249
  },
4202
4250
  {
4203
4251
  "name": "<impl Serialize for u16>::stream_serialize",
4204
- "start": 3276
4252
+ "start": 2467
4205
4253
  },
4206
4254
  {
4207
4255
  "name": "<impl Deserialize for u16>::deserialize",
4208
- "start": 3442
4256
+ "start": 2633
4209
4257
  },
4210
4258
  {
4211
4259
  "name": "<impl Deserialize for u16>::stream_deserialize",
4212
- "start": 3688
4260
+ "start": 2879
4213
4261
  },
4214
4262
  {
4215
4263
  "name": "<impl Serialize for u32>::serialize",
4216
- "start": 3834
4264
+ "start": 3025
4217
4265
  },
4218
4266
  {
4219
4267
  "name": "<impl Serialize for u32>::stream_serialize",
4220
- "start": 4055
4268
+ "start": 3246
4221
4269
  },
4222
4270
  {
4223
4271
  "name": "<impl Deserialize for u32>::deserialize",
4224
- "start": 4221
4272
+ "start": 3412
4225
4273
  },
4226
4274
  {
4227
4275
  "name": "<impl Deserialize for u32>::stream_deserialize",
4228
- "start": 4467
4276
+ "start": 3658
4229
4277
  },
4230
4278
  {
4231
4279
  "name": "<impl Serialize for u64>::serialize",
4232
- "start": 4613
4280
+ "start": 3804
4233
4281
  },
4234
4282
  {
4235
4283
  "name": "<impl Serialize for u64>::stream_serialize",
4236
- "start": 4834
4284
+ "start": 4025
4237
4285
  },
4238
4286
  {
4239
4287
  "name": "<impl Deserialize for u64>::deserialize",
4240
- "start": 5000
4288
+ "start": 4191
4241
4289
  },
4242
4290
  {
4243
4291
  "name": "<impl Deserialize for u64>::stream_deserialize",
4244
- "start": 5246
4292
+ "start": 4437
4245
4293
  },
4246
4294
  {
4247
4295
  "name": "<impl Serialize for u128>::serialize",
4248
- "start": 5394
4296
+ "start": 4585
4249
4297
  },
4250
4298
  {
4251
4299
  "name": "<impl Serialize for u128>::stream_serialize",
4252
- "start": 5615
4300
+ "start": 4806
4253
4301
  },
4254
4302
  {
4255
4303
  "name": "<impl Deserialize for u128>::deserialize",
4256
- "start": 5783
4304
+ "start": 4974
4257
4305
  },
4258
4306
  {
4259
4307
  "name": "<impl Deserialize for u128>::stream_deserialize",
4260
- "start": 6029
4308
+ "start": 5220
4261
4309
  },
4262
4310
  {
4263
4311
  "name": "<impl Serialize for Field>::serialize",
4264
- "start": 6180
4312
+ "start": 5371
4265
4313
  },
4266
4314
  {
4267
4315
  "name": "<impl Serialize for Field>::stream_serialize",
4268
- "start": 6401
4316
+ "start": 5592
4269
4317
  },
4270
4318
  {
4271
4319
  "name": "<impl Deserialize for Field>::deserialize",
4272
- "start": 6562
4320
+ "start": 5753
4273
4321
  },
4274
4322
  {
4275
4323
  "name": "<impl Deserialize for Field>::stream_deserialize",
4276
- "start": 6808
4324
+ "start": 5999
4277
4325
  },
4278
4326
  {
4279
4327
  "name": "<impl Serialize for i8>::serialize",
4280
- "start": 6945
4328
+ "start": 6136
4281
4329
  },
4282
4330
  {
4283
4331
  "name": "<impl Serialize for i8>::stream_serialize",
4284
- "start": 7166
4332
+ "start": 6357
4285
4333
  },
4286
4334
  {
4287
4335
  "name": "<impl Deserialize for i8>::deserialize",
4288
- "start": 7336
4336
+ "start": 6527
4289
4337
  },
4290
4338
  {
4291
4339
  "name": "<impl Deserialize for i8>::stream_deserialize",
4292
- "start": 7582
4340
+ "start": 6773
4293
4341
  },
4294
4342
  {
4295
4343
  "name": "<impl Serialize for i16>::serialize",
4296
- "start": 7733
4344
+ "start": 6924
4297
4345
  },
4298
4346
  {
4299
4347
  "name": "<impl Serialize for i16>::stream_serialize",
4300
- "start": 7954
4348
+ "start": 7145
4301
4349
  },
4302
4350
  {
4303
4351
  "name": "<impl Deserialize for i16>::deserialize",
4304
- "start": 8127
4352
+ "start": 7318
4305
4353
  },
4306
4354
  {
4307
4355
  "name": "<impl Deserialize for i16>::stream_deserialize",
4308
- "start": 8373
4356
+ "start": 7564
4309
4357
  },
4310
4358
  {
4311
4359
  "name": "<impl Serialize for i32>::serialize",
4312
- "start": 8526
4360
+ "start": 7717
4313
4361
  },
4314
4362
  {
4315
4363
  "name": "<impl Serialize for i32>::stream_serialize",
4316
- "start": 8747
4364
+ "start": 7938
4317
4365
  },
4318
4366
  {
4319
4367
  "name": "<impl Deserialize for i32>::deserialize",
4320
- "start": 8920
4368
+ "start": 8111
4321
4369
  },
4322
4370
  {
4323
4371
  "name": "<impl Deserialize for i32>::stream_deserialize",
4324
- "start": 9166
4372
+ "start": 8357
4325
4373
  },
4326
4374
  {
4327
4375
  "name": "<impl Serialize for i64>::serialize",
4328
- "start": 9319
4376
+ "start": 8510
4329
4377
  },
4330
4378
  {
4331
4379
  "name": "<impl Serialize for i64>::stream_serialize",
4332
- "start": 9540
4380
+ "start": 8731
4333
4381
  },
4334
4382
  {
4335
4383
  "name": "<impl Deserialize for i64>::deserialize",
4336
- "start": 9713
4384
+ "start": 8904
4337
4385
  },
4338
4386
  {
4339
4387
  "name": "<impl Deserialize for i64>::stream_deserialize",
4340
- "start": 9959
4388
+ "start": 9150
4341
4389
  },
4342
4390
  {
4343
4391
  "name": "<impl Serialize for [T; M]>::serialize",
4344
- "start": 10159
4392
+ "start": 9350
4345
4393
  },
4346
4394
  {
4347
4395
  "name": "<impl Serialize for [T; M]>::stream_serialize",
4348
- "start": 10380
4396
+ "start": 9571
4349
4397
  },
4350
4398
  {
4351
4399
  "name": "<impl Deserialize for [T; M]>::deserialize",
4352
- "start": 10640
4400
+ "start": 9831
4353
4401
  },
4354
4402
  {
4355
4403
  "name": "<impl Deserialize for [T; M]>::stream_deserialize",
4356
- "start": 10886
4404
+ "start": 10077
4357
4405
  },
4358
4406
  {
4359
4407
  "name": "<impl Serialize for Option<T>>::serialize",
4360
- "start": 11198
4408
+ "start": 10389
4361
4409
  },
4362
4410
  {
4363
4411
  "name": "<impl Serialize for Option<T>>::stream_serialize",
4364
- "start": 11419
4412
+ "start": 10610
4365
4413
  },
4366
4414
  {
4367
4415
  "name": "<impl Deserialize for Option<T>>::deserialize",
4368
- "start": 11806
4416
+ "start": 10997
4369
4417
  },
4370
4418
  {
4371
4419
  "name": "<impl Deserialize for Option<T>>::stream_deserialize",
4372
- "start": 12052
4420
+ "start": 11243
4373
4421
  },
4374
4422
  {
4375
4423
  "name": "<impl Serialize for EmbeddedCurveScalar>::serialize",
4376
- "start": 12430
4424
+ "start": 11621
4377
4425
  },
4378
4426
  {
4379
4427
  "name": "<impl Serialize for EmbeddedCurveScalar>::stream_serialize",
4380
- "start": 12553
4428
+ "start": 11744
4381
4429
  },
4382
4430
  {
4383
4431
  "name": "<impl Deserialize for EmbeddedCurveScalar>::deserialize",
4384
- "start": 12753
4432
+ "start": 11944
4385
4433
  },
4386
4434
  {
4387
4435
  "name": "<impl Deserialize for EmbeddedCurveScalar>::stream_deserialize",
4388
- "start": 12899
4436
+ "start": 12090
4389
4437
  },
4390
4438
  {
4391
4439
  "name": "<impl Serialize for EmbeddedCurvePoint>::serialize",
4392
- "start": 13106
4440
+ "start": 12297
4393
4441
  },
4394
4442
  {
4395
4443
  "name": "<impl Serialize for EmbeddedCurvePoint>::stream_serialize",
4396
- "start": 13233
4444
+ "start": 12397
4397
4445
  },
4398
4446
  {
4399
4447
  "name": "<impl Deserialize for EmbeddedCurvePoint>::deserialize",
4400
- "start": 13478
4448
+ "start": 12593
4401
4449
  },
4402
4450
  {
4403
4451
  "name": "<impl Deserialize for EmbeddedCurvePoint>::stream_deserialize",
4404
- "start": 13651
4452
+ "start": 12737
4405
4453
  },
4406
4454
  {
4407
4455
  "name": "<impl Deserialize for str<M>>::deserialize",
4408
- "start": 13863
4456
+ "start": 12916
4409
4457
  },
4410
4458
  {
4411
4459
  "name": "<impl Deserialize for str<M>>::stream_deserialize",
4412
- "start": 14109
4460
+ "start": 13162
4413
4461
  },
4414
4462
  {
4415
4463
  "name": "<impl Serialize for str<M>>::serialize",
4416
- "start": 14342
4464
+ "start": 13395
4417
4465
  },
4418
4466
  {
4419
4467
  "name": "<impl Serialize for str<M>>::stream_serialize",
4420
- "start": 14563
4468
+ "start": 13616
4421
4469
  },
4422
4470
  {
4423
4471
  "name": "<impl Deserialize for BoundedVec<T, M>>::deserialize",
4424
- "start": 14944
4472
+ "start": 13997
4425
4473
  },
4426
4474
  {
4427
4475
  "name": "<impl Deserialize for BoundedVec<T, M>>::stream_deserialize",
4428
- "start": 15190
4476
+ "start": 14243
4429
4477
  },
4430
4478
  {
4431
4479
  "name": "<impl Deserialize for ()>::deserialize",
4432
- "start": 16246
4480
+ "start": 15299
4433
4481
  },
4434
4482
  {
4435
4483
  "name": "<impl Deserialize for ()>::stream_deserialize",
4436
- "start": 16493
4484
+ "start": 15546
4437
4485
  },
4438
4486
  {
4439
4487
  "name": "<impl Serialize for BoundedVec<T, M>>::serialize",
4440
- "start": 16858
4488
+ "start": 15911
4441
4489
  },
4442
4490
  {
4443
4491
  "name": "<impl Serialize for BoundedVec<T, M>>::stream_serialize",
4444
- "start": 17079
4492
+ "start": 16132
4445
4493
  },
4446
4494
  {
4447
4495
  "name": "make_slice",
4448
- "start": 17564
4496
+ "start": 16617
4449
4497
  },
4450
4498
  {
4451
4499
  "name": "impl_serialize_for_tuple",
4452
- "start": 17814
4500
+ "start": 16867
4453
4501
  },
4454
4502
  {
4455
4503
  "name": "<impl Serialize for (T1,)>::serialize",
4456
- "start": 21105
4504
+ "start": 20158
4457
4505
  },
4458
4506
  {
4459
4507
  "name": "<impl Serialize for (T1,)>::stream_serialize",
4460
- "start": 21356
4508
+ "start": 20409
4461
4509
  },
4462
4510
  {
4463
4511
  "name": "<impl Deserialize for (T1,)>::deserialize",
4464
- "start": 21563
4512
+ "start": 20616
4465
4513
  },
4466
4514
  {
4467
4515
  "name": "<impl Deserialize for (T1,)>::stream_deserialize",
4468
- "start": 21824
4516
+ "start": 20877
4469
4517
  },
4470
4518
  {
4471
4519
  "name": "bounded_vec_serialization",
4472
- "start": 22173
4520
+ "start": 21226
4473
4521
  }
4474
4522
  ],
4475
4523
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/type_impls.nr",
4476
- "source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal U1_SERIALIZED_LEN: u32 = 1;\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u1 {\n let N: u32 = U1_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u1 {\n let N: u32 = U1_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u1\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write_bool(self.is_some());\n if self.is_some() {\n self.unwrap_unchecked().stream_serialize(writer);\n } else {\n writer.advance_offset(<T as Serialize>::N);\n }\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 3;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y, self.is_infinite as Field]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n writer.write(self.is_infinite as Field);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1], is_infinite: fields[2] != 0 }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read(), is_infinite: reader.read_bool() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = reader.peek_offset(payload_len) as u32;\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(self.len() as u32);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec<Field, 3> = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::<Field, 3>::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"
4477
- },
4478
- "3": {
4479
- "function_locations": [
4480
- {
4481
- "name": "[T; N]::len",
4482
- "start": 480
4483
- },
4484
- {
4485
- "name": "[T; N]::as_vector",
4486
- "start": 735
4487
- },
4488
- {
4489
- "name": "[T; N]::as_slice",
4490
- "start": 1112
4491
- },
4492
- {
4493
- "name": "[T; N]::map",
4494
- "start": 1442
4495
- },
4496
- {
4497
- "name": "[T; N]::mapi",
4498
- "start": 2002
4499
- },
4500
- {
4501
- "name": "[T; N]::for_each",
4502
- "start": 2549
4503
- },
4504
- {
4505
- "name": "[T; N]::for_eachi",
4506
- "start": 2966
4507
- },
4508
- {
4509
- "name": "[T; N]::fold",
4510
- "start": 3832
4511
- },
4512
- {
4513
- "name": "[T; N]::reduce",
4514
- "start": 4349
4515
- },
4516
- {
4517
- "name": "[T; N]::all",
4518
- "start": 4858
4519
- },
4520
- {
4521
- "name": "[T; N]::any",
4522
- "start": 5330
4523
- },
4524
- {
4525
- "name": "[T; N]::concat",
4526
- "start": 5872
4527
- },
4528
- {
4529
- "name": "[T; N]::sort",
4530
- "start": 6768
4531
- },
4532
- {
4533
- "name": "[T; N]::sort_via",
4534
- "start": 7783
4535
- },
4536
- {
4537
- "name": "[u8; N]::as_str_unchecked",
4538
- "start": 8811
4539
- },
4540
- {
4541
- "name": "<impl From<str<N>> for [u8; N]>::from",
4542
- "start": 8938
4543
- },
4544
- {
4545
- "name": "test::map_empty",
4546
- "start": 9012
4547
- },
4548
- {
4549
- "name": "test::sort_u32",
4550
- "start": 10122
4551
- },
4552
- {
4553
- "name": "test::test_sort",
4554
- "start": 10177
4555
- },
4556
- {
4557
- "name": "test::test_sort_100_values",
4558
- "start": 10408
4559
- },
4560
- {
4561
- "name": "test::test_sort_100_values_comptime",
4562
- "start": 11576
4563
- },
4564
- {
4565
- "name": "test::test_sort_via",
4566
- "start": 11721
4567
- },
4568
- {
4569
- "name": "test::test_sort_via_100_values",
4570
- "start": 11968
4571
- },
4572
- {
4573
- "name": "test::mapi_empty",
4574
- "start": 13129
4575
- },
4576
- {
4577
- "name": "test::for_each_empty",
4578
- "start": 13224
4579
- },
4580
- {
4581
- "name": "test::for_eachi_empty",
4582
- "start": 13362
4583
- },
4584
- {
4585
- "name": "test::map_example",
4586
- "start": 13501
4587
- },
4588
- {
4589
- "name": "test::mapi_example",
4590
- "start": 13638
4591
- },
4592
- {
4593
- "name": "test::for_each_example",
4594
- "start": 13787
4595
- },
4596
- {
4597
- "name": "test::for_eachi_example",
4598
- "start": 14127
4599
- },
4600
- {
4601
- "name": "test::concat",
4602
- "start": 14338
4603
- },
4604
- {
4605
- "name": "test::concat_zero_length_with_something",
4606
- "start": 14597
4607
- },
4608
- {
4609
- "name": "test::concat_something_with_zero_length",
4610
- "start": 14800
4611
- },
4612
- {
4613
- "name": "test::concat_zero_lengths",
4614
- "start": 14989
4615
- }
4616
- ],
4617
- "path": "std/array/mod.nr",
4618
- "source": "use crate::cmp::{Eq, Ord};\nuse crate::convert::From;\nuse crate::runtime::is_unconstrained;\n\nmod check_shuffle;\nmod quicksort;\n\nimpl<T, let N: u32> [T; N] {\n /// Returns the length of this array.\n ///\n /// ```noir\n /// fn len(self) -> Field\n /// ```\n ///\n /// example\n ///\n /// ```noir\n /// fn main() {\n /// let array = [42, 42];\n /// assert(array.len() == 2);\n /// }\n /// ```\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Returns this array as a vector.\n ///\n /// ```noir\n /// let array = [1, 2];\n /// let vector = array.as_vector();\n /// assert_eq(vector, [1, 2].as_vector());\n /// ```\n #[builtin(as_vector)]\n pub fn as_vector(self) -> [T] {}\n\n /// Returns this array as a vector.\n /// This method is deprecated in favor of `as_vector`.\n ///\n /// ```noir\n /// let array = [1, 2];\n /// let vector = array.as_slice();\n /// assert_eq(vector, [1, 2].as_vector());\n /// ```\n #[builtin(as_vector)]\n #[deprecated(\"This method has been renamed to `as_vector`\")]\n pub fn as_slice(self) -> [T] {}\n\n /// Applies a function to each element of this array, returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.map(|a| a * 2);\n /// assert_eq(b, [2, 4, 6]);\n /// ```\n pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array along with its index,\n /// returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.mapi(|i, a| i + a * 2);\n /// assert_eq(b, [2, 5, 8]);\n /// ```\n pub fn mapi<U, Env>(self, f: fn[Env](u32, T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(i, self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// let mut i = 0;\n /// a.for_each(|x| {\n /// b[i] = x;\n /// i += 1;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_each<Env>(self, f: fn[Env](T) -> ()) {\n for i in 0..self.len() {\n f(self[i]);\n }\n }\n\n /// Applies a function to each element of this array along with its index.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// a.for_eachi(|i, x| {\n /// b[i] = x;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_eachi<Env>(self, f: fn[Env](u32, T) -> ()) {\n for i in 0..self.len() {\n f(i, self[i]);\n }\n }\n\n /// Applies a function to each element of the array, returning the final accumulated value. The first\n /// parameter is the initial value.\n ///\n /// This is a left fold, so the given function will be applied to the accumulator and first element of\n /// the array, then the second, and so on. For a given call the expected result would be equivalent to:\n ///\n /// ```rust\n /// let a1 = [1];\n /// let a2 = [1, 2];\n /// let a3 = [1, 2, 3];\n ///\n /// let f = |a, b| a - b;\n /// a1.fold(10, f); //=> f(10, 1)\n /// a2.fold(10, f); //=> f(f(10, 1), 2)\n /// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3)\n ///\n /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3);\n /// ```\n pub fn fold<U, Env>(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n /// Same as fold, but uses the first element as the starting element.\n ///\n /// Requires the input array to be non-empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [1, 2, 3, 4];\n /// let reduced = arr.reduce(|a, b| a + b);\n /// assert(reduced == 10);\n /// }\n /// ```\n pub fn reduce<Env>(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n /// Returns true if all the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 2];\n /// let all = arr.all(|a| a == 2);\n /// assert(all);\n /// }\n /// ```\n pub fn all<Env>(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n /// Returns true if any of the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 5];\n /// let any = arr.any(|a| a == 5);\n /// assert(any);\n /// }\n /// ```\n pub fn any<Env>(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n\n /// Concatenates this array with another array.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr1 = [1, 2, 3, 4];\n /// let arr2 = [6, 7, 8, 9, 10, 11];\n /// let concatenated_arr = arr1.concat(arr2);\n /// assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n /// }\n /// ```\n pub fn concat<let M: u32>(self, array2: [T; M]) -> [T; N + M] {\n let mut result = [crate::mem::zeroed(); N + M];\n for i in 0..N {\n result[i] = self[i];\n }\n for i in 0..M {\n result[i + N] = array2[i];\n }\n result\n }\n}\n\nimpl<T, let N: u32> [T; N]\nwhere\n T: Ord + Eq,\n{\n /// Returns a new sorted array. The original array remains untouched. Notice that this function will\n /// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting\n /// logic it uses internally is optimized specifically for these values. If you need a sort function to\n /// sort any type, you should use the [`Self::sort_via`] function.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32];\n /// let sorted = arr.sort();\n /// assert(sorted == [32, 42]);\n /// }\n /// ```\n pub fn sort(self) -> Self {\n self.sort_via(|a, b| a <= b)\n }\n}\n\nimpl<T, let N: u32> [T; N]\nwhere\n T: Eq,\n{\n /// Returns a new sorted array by sorting it with a custom comparison function.\n /// The original array remains untouched.\n /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument.\n ///\n /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32]\n /// let sorted_ascending = arr.sort_via(|a, b| a <= b);\n /// assert(sorted_ascending == [32, 42]); // verifies\n ///\n /// let sorted_descending = arr.sort_via(|a, b| a >= b);\n /// assert(sorted_descending == [32, 42]); // does not verify\n /// }\n /// ```\n pub fn sort_via<Env>(self, ordering: fn[Env](T, T) -> bool) -> Self {\n // Safety: `sorted` array is checked to be:\n // a. a permutation of `input`'s elements\n // b. satisfying the predicate `ordering`\n let sorted = unsafe { quicksort::quicksort(self, ordering) };\n\n if !is_unconstrained() {\n for i in 0..N - 1 {\n assert(\n ordering(sorted[i], sorted[i + 1]),\n \"Array has not been sorted correctly according to `ordering`.\",\n );\n }\n check_shuffle::check_shuffle(self, sorted);\n }\n sorted\n }\n}\n\nimpl<let N: u32> [u8; N] {\n /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation -\n /// the given array is interpreted as-is as a string.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let hi = [104, 105].as_str_unchecked();\n /// assert_eq(hi, \"hi\");\n /// }\n /// ```\n #[builtin(array_as_str_unchecked)]\n pub fn as_str_unchecked(self) -> str<N> {}\n}\n\nimpl<let N: u32> From<str<N>> for [u8; N] {\n /// Returns an array of the string bytes.\n fn from(s: str<N>) -> Self {\n s.as_bytes()\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq([].map(|x| x + 1), []);\n }\n\n global arr_with_100_values: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54,\n 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98,\n 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, 43, 86, 35,\n 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15, 127, 81, 30, 8,\n 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n global expected_with_100_values: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30, 32,\n 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58, 61, 62,\n 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82, 84, 84, 86,\n 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114, 114, 116, 118,\n 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n fn sort_u32(a: u32, b: u32) -> bool {\n a <= b\n }\n\n #[test]\n fn test_sort() {\n let arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort();\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values() {\n let arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort();\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values_comptime() {\n let sorted = arr_with_100_values.sort();\n assert(sorted == expected_with_100_values);\n }\n\n #[test]\n fn test_sort_via() {\n let arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_via_100_values() {\n let arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq([].mapi(|i, x| i * x + 1), []);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_each(|_x| assert(false));\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_eachi(|_i, _x| assert(false));\n }\n\n #[test]\n fn map_example() {\n let a = [1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, [2, 4, 6]);\n }\n\n #[test]\n fn mapi_example() {\n let a = [1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn for_each_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n let mut i = 0;\n let i_ref = &mut i;\n a.for_each(|x| {\n b_ref[*i_ref] = x * 2;\n *i_ref += 1;\n });\n assert_eq(b, [2, 4, 6]);\n assert_eq(i, 3);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { b_ref[i] = i + a * 2; });\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn concat() {\n let arr1 = [1, 2, 3, 4];\n let arr2 = [6, 7, 8, 9, 10, 11];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n }\n\n #[test]\n fn concat_zero_length_with_something() {\n let arr1 = [];\n let arr2 = [1];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_something_with_zero_length() {\n let arr1 = [1];\n let arr2 = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_zero_lengths() {\n let arr1: [Field; 0] = [];\n let arr2: [Field; 0] = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, []);\n }\n}\n"
4524
+ "source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write_bool(self.is_some());\n if self.is_some() {\n self.unwrap_unchecked().stream_serialize(writer);\n } else {\n writer.advance_offset(<T as Serialize>::N);\n }\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = reader.peek_offset(payload_len) as u32;\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(self.len() as u32);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec<Field, 3> = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::<Field, 3>::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"
4619
4525
  },
4620
4526
  "41": {
4621
4527
  "function_locations": [
@@ -4629,91 +4535,91 @@
4629
4535
  },
4630
4536
  {
4631
4537
  "name": "Option<T>::is_none",
4632
- "start": 671
4538
+ "start": 672
4633
4539
  },
4634
4540
  {
4635
4541
  "name": "Option<T>::is_some",
4636
- "start": 772
4542
+ "start": 774
4637
4543
  },
4638
4544
  {
4639
4545
  "name": "Option<T>::unwrap",
4640
- "start": 896
4546
+ "start": 898
4641
4547
  },
4642
4548
  {
4643
4549
  "name": "Option<T>::unwrap_unchecked",
4644
- "start": 1194
4550
+ "start": 1196
4645
4551
  },
4646
4552
  {
4647
4553
  "name": "Option<T>::unwrap_or",
4648
- "start": 1366
4554
+ "start": 1368
4649
4555
  },
4650
4556
  {
4651
4557
  "name": "Option<T>::unwrap_or_else",
4652
- "start": 1666
4558
+ "start": 1668
4653
4559
  },
4654
4560
  {
4655
4561
  "name": "Option<T>::expect",
4656
- "start": 1967
4562
+ "start": 1969
4657
4563
  },
4658
4564
  {
4659
4565
  "name": "Option<T>::map",
4660
- "start": 2188
4566
+ "start": 2190
4661
4567
  },
4662
4568
  {
4663
4569
  "name": "Option<T>::map_or",
4664
- "start": 2488
4570
+ "start": 2490
4665
4571
  },
4666
4572
  {
4667
4573
  "name": "Option<T>::map_or_else",
4668
- "start": 2782
4574
+ "start": 2784
4669
4575
  },
4670
4576
  {
4671
4577
  "name": "Option<T>::and",
4672
- "start": 3007
4578
+ "start": 3009
4673
4579
  },
4674
4580
  {
4675
4581
  "name": "Option<T>::and_then",
4676
- "start": 3444
4582
+ "start": 3446
4677
4583
  },
4678
4584
  {
4679
4585
  "name": "Option<T>::or",
4680
- "start": 3667
4586
+ "start": 3669
4681
4587
  },
4682
4588
  {
4683
4589
  "name": "Option<T>::or_else",
4684
- "start": 3900
4590
+ "start": 3902
4685
4591
  },
4686
4592
  {
4687
4593
  "name": "Option<T>::xor",
4688
- "start": 4190
4594
+ "start": 4192
4689
4595
  },
4690
4596
  {
4691
4597
  "name": "Option<T>::filter",
4692
- "start": 4634
4598
+ "start": 4636
4693
4599
  },
4694
4600
  {
4695
4601
  "name": "Option<T>::flatten",
4696
- "start": 5063
4602
+ "start": 5065
4697
4603
  },
4698
4604
  {
4699
4605
  "name": "<impl Default for Option<T>>::default",
4700
- "start": 5240
4606
+ "start": 5242
4701
4607
  },
4702
4608
  {
4703
4609
  "name": "<impl Eq for Option<T>>::eq",
4704
- "start": 5355
4610
+ "start": 5357
4705
4611
  },
4706
4612
  {
4707
4613
  "name": "<impl Hash for Option<T>>::hash",
4708
- "start": 5704
4614
+ "start": 5706
4709
4615
  },
4710
4616
  {
4711
4617
  "name": "<impl Ord for Option<T>>::cmp",
4712
- "start": 5973
4618
+ "start": 5975
4713
4619
  }
4714
4620
  ],
4715
4621
  "path": "std/option.nr",
4716
- "source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\n/// Represents a value of type T or its absence.\n/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one.\npub struct Option<T> {\n _is_some: bool,\n _value: T,\n}\n\nimpl<T> Option<T> {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else<Env>(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect<let N: u32, MessageTypes>(self, message: fmtstr<N, MessageTypes>) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> Option<U> {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or<U, Env>(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else<U, Env1, Env2>(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then<U, Env>(self, f: fn[Env](T) -> Option<U>) -> Option<U> {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else<Env>(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter<Env>(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option<Option<T>> into a Option<T>.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option<Option<T>>) -> Option<T> {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl<T> Default for Option<T> {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl<T> Eq for Option<T>\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl<T> Hash for Option<T>\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl<T> Ord for Option<T>\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n"
4622
+ "source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\n/// Represents a value of type T or its absence.\n/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one.\npub struct Option<T> {\n _is_some: bool,\n _value: T,\n}\n\nimpl<T> Option<T> {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(&self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(&self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else<Env>(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect<let N: u32, MessageTypes>(self, message: fmtstr<N, MessageTypes>) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> Option<U> {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or<U, Env>(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else<U, Env1, Env2>(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then<U, Env>(self, f: fn[Env](T) -> Option<U>) -> Option<U> {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else<Env>(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter<Env>(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option<Option<T>> into a Option<T>.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option<Option<T>>) -> Option<T> {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl<T> Default for Option<T> {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl<T> Eq for Option<T>\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl<T> Hash for Option<T>\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl<T> Ord for Option<T>\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n"
4717
4623
  },
4718
4624
  "42": {
4719
4625
  "function_locations": [
@@ -4755,241 +4661,237 @@
4755
4661
  "name": "<impl Eq for u8>::eq",
4756
4662
  "start": 1282
4757
4663
  },
4758
- {
4759
- "name": "<impl Eq for u1>::eq",
4760
- "start": 1366
4761
- },
4762
4664
  {
4763
4665
  "name": "<impl Eq for i8>::eq",
4764
- "start": 1451
4666
+ "start": 1366
4765
4667
  },
4766
4668
  {
4767
4669
  "name": "<impl Eq for i16>::eq",
4768
- "start": 1537
4670
+ "start": 1452
4769
4671
  },
4770
4672
  {
4771
4673
  "name": "<impl Eq for i32>::eq",
4772
- "start": 1623
4674
+ "start": 1538
4773
4675
  },
4774
4676
  {
4775
4677
  "name": "<impl Eq for i64>::eq",
4776
- "start": 1709
4678
+ "start": 1624
4777
4679
  },
4778
4680
  {
4779
4681
  "name": "<impl Eq for ()>::eq",
4780
- "start": 1802
4682
+ "start": 1717
4781
4683
  },
4782
4684
  {
4783
4685
  "name": "<impl Eq for bool>::eq",
4784
- "start": 1881
4686
+ "start": 1796
4785
4687
  },
4786
4688
  {
4787
4689
  "name": "<impl Eq for [T; N]>::eq",
4788
- "start": 2006
4690
+ "start": 1921
4789
4691
  },
4790
4692
  {
4791
4693
  "name": "<impl Eq for [T]>::eq",
4792
- "start": 2224
4694
+ "start": 2139
4793
4695
  },
4794
4696
  {
4795
4697
  "name": "<impl Eq for str<N>>::eq",
4796
- "start": 2503
4698
+ "start": 2418
4797
4699
  },
4798
4700
  {
4799
4701
  "name": "make_tuple_eq_body",
4800
- "start": 2683
4702
+ "start": 2598
4801
4703
  },
4802
4704
  {
4803
4705
  "name": "<impl Eq for (A, B)>::eq",
4804
- "start": 2944
4706
+ "start": 2859
4805
4707
  },
4806
4708
  {
4807
4709
  "name": "<impl Eq for (A, B, C)>::eq",
4808
- "start": 3076
4710
+ "start": 2991
4809
4711
  },
4810
4712
  {
4811
4713
  "name": "<impl Eq for (A, B, C, D)>::eq",
4812
- "start": 3221
4714
+ "start": 3136
4813
4715
  },
4814
4716
  {
4815
4717
  "name": "<impl Eq for (A, B, C, D, E)>::eq",
4816
- "start": 3379
4718
+ "start": 3294
4817
4719
  },
4818
4720
  {
4819
4721
  "name": "<impl Eq for (A, B, C, D, E, F)>::eq",
4820
- "start": 3550
4722
+ "start": 3465
4821
4723
  },
4822
4724
  {
4823
4725
  "name": "<impl Eq for (A, B, C, D, E, F, G)>::eq",
4824
- "start": 3734
4726
+ "start": 3649
4825
4727
  },
4826
4728
  {
4827
4729
  "name": "<impl Eq for (A, B, C, D, E, F, G, H)>::eq",
4828
- "start": 3931
4730
+ "start": 3846
4829
4731
  },
4830
4732
  {
4831
4733
  "name": "<impl Eq for (A, B, C, D, E, F, G, H, I)>::eq",
4832
- "start": 4141
4734
+ "start": 4056
4833
4735
  },
4834
4736
  {
4835
4737
  "name": "<impl Eq for (A, B, C, D, E, F, G, H, I, J)>::eq",
4836
- "start": 4364
4738
+ "start": 4279
4837
4739
  },
4838
4740
  {
4839
4741
  "name": "<impl Eq for (A, B, C, D, E, F, G, H, I, J, K)>::eq",
4840
- "start": 4601
4742
+ "start": 4516
4841
4743
  },
4842
4744
  {
4843
4745
  "name": "<impl Eq for (A, B, C, D, E, F, G, H, I, J, K, L)>::eq",
4844
- "start": 4851
4746
+ "start": 4766
4845
4747
  },
4846
4748
  {
4847
4749
  "name": "<impl Eq for Ordering>::eq",
4848
- "start": 4961
4750
+ "start": 4876
4849
4751
  },
4850
4752
  {
4851
4753
  "name": "Ordering::less",
4852
- "start": 5562
4754
+ "start": 5477
4853
4755
  },
4854
4756
  {
4855
4757
  "name": "Ordering::equal",
4856
- "start": 5633
4758
+ "start": 5548
4857
4759
  },
4858
4760
  {
4859
4761
  "name": "Ordering::greater",
4860
- "start": 5706
4762
+ "start": 5621
4861
4763
  },
4862
4764
  {
4863
4765
  "name": "derive_ord",
4864
- "start": 6077
4766
+ "start": 5992
4865
4767
  },
4866
4768
  {
4867
4769
  "name": "<impl Ord for u128>::cmp",
4868
- "start": 6727
4770
+ "start": 6642
4869
4771
  },
4870
4772
  {
4871
4773
  "name": "<impl Ord for u64>::cmp",
4872
- "start": 6974
4774
+ "start": 6889
4873
4775
  },
4874
4776
  {
4875
4777
  "name": "<impl Ord for u32>::cmp",
4876
- "start": 7222
4778
+ "start": 7137
4877
4779
  },
4878
4780
  {
4879
4781
  "name": "<impl Ord for u16>::cmp",
4880
- "start": 7470
4782
+ "start": 7385
4881
4783
  },
4882
4784
  {
4883
4785
  "name": "<impl Ord for u8>::cmp",
4884
- "start": 7716
4786
+ "start": 7631
4885
4787
  },
4886
4788
  {
4887
4789
  "name": "<impl Ord for i8>::cmp",
4888
- "start": 7962
4790
+ "start": 7877
4889
4791
  },
4890
4792
  {
4891
4793
  "name": "<impl Ord for i16>::cmp",
4892
- "start": 8210
4794
+ "start": 8125
4893
4795
  },
4894
4796
  {
4895
4797
  "name": "<impl Ord for i32>::cmp",
4896
- "start": 8458
4798
+ "start": 8373
4897
4799
  },
4898
4800
  {
4899
4801
  "name": "<impl Ord for i64>::cmp",
4900
- "start": 8706
4802
+ "start": 8621
4901
4803
  },
4902
4804
  {
4903
4805
  "name": "<impl Ord for ()>::cmp",
4904
- "start": 8960
4806
+ "start": 8875
4905
4807
  },
4906
4808
  {
4907
4809
  "name": "<impl Ord for bool>::cmp",
4908
- "start": 9059
4810
+ "start": 8974
4909
4811
  },
4910
4812
  {
4911
4813
  "name": "<impl Ord for [T; N]>::cmp",
4912
- "start": 9529
4814
+ "start": 9444
4913
4815
  },
4914
4816
  {
4915
4817
  "name": "<impl Ord for [T]>::cmp",
4916
- "start": 9932
4818
+ "start": 9847
4917
4819
  },
4918
4820
  {
4919
4821
  "name": "make_tuple_ord_body",
4920
- "start": 10500
4822
+ "start": 10415
4921
4823
  },
4922
4824
  {
4923
4825
  "name": "<impl Ord for (A, B)>::cmp",
4924
- "start": 11122
4826
+ "start": 11037
4925
4827
  },
4926
4828
  {
4927
4829
  "name": "<impl Ord for (A, B, C)>::cmp",
4928
- "start": 11264
4830
+ "start": 11179
4929
4831
  },
4930
4832
  {
4931
4833
  "name": "<impl Ord for (A, B, C, D)>::cmp",
4932
- "start": 11420
4834
+ "start": 11335
4933
4835
  },
4934
4836
  {
4935
4837
  "name": "<impl Ord for (A, B, C, D, E)>::cmp",
4936
- "start": 11590
4838
+ "start": 11505
4937
4839
  },
4938
4840
  {
4939
4841
  "name": "<impl Ord for (A, B, C, D, E, F)>::cmp",
4940
- "start": 11774
4842
+ "start": 11689
4941
4843
  },
4942
4844
  {
4943
4845
  "name": "<impl Ord for (A, B, C, D, E, F, G)>::cmp",
4944
- "start": 11972
4846
+ "start": 11887
4945
4847
  },
4946
4848
  {
4947
4849
  "name": "<impl Ord for (A, B, C, D, E, F, G, H)>::cmp",
4948
- "start": 12184
4850
+ "start": 12099
4949
4851
  },
4950
4852
  {
4951
4853
  "name": "<impl Ord for (A, B, C, D, E, F, G, H, I)>::cmp",
4952
- "start": 12410
4854
+ "start": 12325
4953
4855
  },
4954
4856
  {
4955
4857
  "name": "<impl Ord for (A, B, C, D, E, F, G, H, I, J)>::cmp",
4956
- "start": 12650
4858
+ "start": 12565
4957
4859
  },
4958
4860
  {
4959
4861
  "name": "<impl Ord for (A, B, C, D, E, F, G, H, I, J, K)>::cmp",
4960
- "start": 12905
4862
+ "start": 12820
4961
4863
  },
4962
4864
  {
4963
4865
  "name": "<impl Ord for (A, B, C, D, E, F, G, H, I, J, K, L)>::cmp",
4964
- "start": 13174
4866
+ "start": 13089
4965
4867
  },
4966
4868
  {
4967
4869
  "name": "max",
4968
- "start": 13536
4870
+ "start": 13451
4969
4871
  },
4970
4872
  {
4971
4873
  "name": "min",
4972
- "start": 13913
4874
+ "start": 13828
4973
4875
  },
4974
4876
  {
4975
4877
  "name": "cmp_tests::sanity_check_min",
4976
- "start": 14067
4878
+ "start": 13982
4977
4879
  },
4978
4880
  {
4979
4881
  "name": "cmp_tests::sanity_check_max",
4980
- "start": 14263
4882
+ "start": 14178
4981
4883
  },
4982
4884
  {
4983
4885
  "name": "cmp_tests::correctly_handles_unequal_length_vectors",
4984
- "start": 14485
4886
+ "start": 14400
4985
4887
  },
4986
4888
  {
4987
4889
  "name": "cmp_tests::lexicographic_ordering_for_vectors",
4988
- "start": 14685
4890
+ "start": 14600
4989
4891
  }
4990
4892
  ],
4991
4893
  "path": "std/cmp.nr",
4992
- "source": "use crate::meta::ctstring::AsCtString;\nuse crate::meta::derive_via;\n\n/// Compare two values for equality\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl<T, let N: u32> Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl<T> Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n }\n result\n }\n}\n\nimpl<let N: u32> Eq for str<N> {\n fn eq(self, other: str<N>) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\ncomptime fn make_tuple_eq_body(n: u32) -> Quoted {\n let mut body = f\"self.0.eq(other.0)\".as_ctstring();\n for i in 1u32..n {\n body = body.append_fmtstr(f\" & self.{i}.eq(other.{i})\");\n }\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Eq, B: Eq> Eq for (A, B) {\n fn eq(self, other: (A, B)) -> bool {\n make_tuple_eq_body!(2u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq> Eq for (A, B, C) {\n fn eq(self, other: (A, B, C)) -> bool {\n make_tuple_eq_body!(3u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq> Eq for (A, B, C, D) {\n fn eq(self, other: (A, B, C, D)) -> bool {\n make_tuple_eq_body!(4u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq> Eq for (A, B, C, D, E) {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n make_tuple_eq_body!(5u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq> Eq for (A, B, C, D, E, F) {\n fn eq(self, other: (A, B, C, D, E, F)) -> bool {\n make_tuple_eq_body!(6u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq> Eq for (A, B, C, D, E, F, G) {\n fn eq(self, other: (A, B, C, D, E, F, G)) -> bool {\n make_tuple_eq_body!(7u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq> Eq for (A, B, C, D, E, F, G, H) {\n fn eq(self, other: (A, B, C, D, E, F, G, H)) -> bool {\n make_tuple_eq_body!(8u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq> Eq for (A, B, C, D, E, F, G, H, I) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I)) -> bool {\n make_tuple_eq_body!(9u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq> Eq for (A, B, C, D, E, F, G, H, I, J) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J)) -> bool {\n make_tuple_eq_body!(10u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> bool {\n make_tuple_eq_body!(11u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq, L: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> bool {\n make_tuple_eq_body!(12u32)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\n/// A value with three states: `Ordering::less()`, `Ordering::equal()` or `Ordering::greater()`.\n/// Most often used to encode the result of a comparison operation.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n/// Compare one object to another, returning whether it is less-than, equal-to,\n/// or greater-than the other object.\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl<T, let N: u32> Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl<T> Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\ncomptime fn make_tuple_ord_body(n: u32) -> Quoted {\n let last = n - 1u32;\n let mut body = if last == 1 {\n f\"let result = self.0.cmp(other.0);\".as_ctstring()\n } else {\n f\"let mut result = self.0.cmp(other.0);\".as_ctstring()\n };\n for i in 1u32..last {\n body = body.append_fmtstr(\n f\" if result == Ordering::equal() {{ result = self.{i}.cmp(other.{i}); }}\",\n );\n }\n body = body.append_fmtstr(\n f\" if result != Ordering::equal() {{ result }} else {{ self.{last}.cmp(other.{last}) }}\",\n );\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Ord, B: Ord> Ord for (A, B) {\n fn cmp(self, other: (A, B)) -> Ordering {\n make_tuple_ord_body!(2u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord> Ord for (A, B, C) {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n make_tuple_ord_body!(3u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord> Ord for (A, B, C, D) {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n make_tuple_ord_body!(4u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord> Ord for (A, B, C, D, E) {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n make_tuple_ord_body!(5u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord> Ord for (A, B, C, D, E, F) {\n fn cmp(self, other: (A, B, C, D, E, F)) -> Ordering {\n make_tuple_ord_body!(6u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord> Ord for (A, B, C, D, E, F, G) {\n fn cmp(self, other: (A, B, C, D, E, F, G)) -> Ordering {\n make_tuple_ord_body!(7u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord> Ord for (A, B, C, D, E, F, G, H) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H)) -> Ordering {\n make_tuple_ord_body!(8u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord> Ord for (A, B, C, D, E, F, G, H, I) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I)) -> Ordering {\n make_tuple_ord_body!(9u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord> Ord for (A, B, C, D, E, F, G, H, I, J) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J)) -> Ordering {\n make_tuple_ord_body!(10u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> Ordering {\n make_tuple_ord_body!(11u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord, L: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> Ordering {\n make_tuple_ord_body!(12u32)\n }\n}\n\n/// Compares and returns the maximum of two values.\n///\n/// Returns the second argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::max(1, 2), 2);\n/// assert_eq(cmp::max(2, 2), 2);\n/// ```\npub fn max<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n/// Compares and returns the minimum of two values.\n///\n/// Returns the first argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::min(1, 2), 1);\n/// assert_eq(cmp::min(2, 2), 2);\n/// ```\npub fn min<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_vectors() {\n let vector_1 = [0, 1, 2, 3].as_vector();\n let vector_2 = [0, 1, 2].as_vector();\n assert(!vector_1.eq(vector_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_vectors() {\n assert(\n [2_u32].as_vector().cmp([1_u32, 1_u32, 1_u32].as_vector())\n == super::Ordering::greater(),\n );\n assert(\n [1_u32, 2_u32].as_vector().cmp([1_u32, 2_u32, 3_u32].as_vector())\n == super::Ordering::less(),\n );\n }\n}\n"
4894
+ "source": "use crate::meta::ctstring::AsCtString;\nuse crate::meta::derive_via;\n\n/// Compare two values for equality\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl<T, let N: u32> Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl<T> Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n }\n result\n }\n}\n\nimpl<let N: u32> Eq for str<N> {\n fn eq(self, other: str<N>) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\ncomptime fn make_tuple_eq_body(n: u32) -> Quoted {\n let mut body = f\"self.0.eq(other.0)\".as_ctstring();\n for i in 1u32..n {\n body = body.append_fmtstr(f\" & self.{i}.eq(other.{i})\");\n }\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Eq, B: Eq> Eq for (A, B) {\n fn eq(self, other: (A, B)) -> bool {\n make_tuple_eq_body!(2u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq> Eq for (A, B, C) {\n fn eq(self, other: (A, B, C)) -> bool {\n make_tuple_eq_body!(3u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq> Eq for (A, B, C, D) {\n fn eq(self, other: (A, B, C, D)) -> bool {\n make_tuple_eq_body!(4u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq> Eq for (A, B, C, D, E) {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n make_tuple_eq_body!(5u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq> Eq for (A, B, C, D, E, F) {\n fn eq(self, other: (A, B, C, D, E, F)) -> bool {\n make_tuple_eq_body!(6u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq> Eq for (A, B, C, D, E, F, G) {\n fn eq(self, other: (A, B, C, D, E, F, G)) -> bool {\n make_tuple_eq_body!(7u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq> Eq for (A, B, C, D, E, F, G, H) {\n fn eq(self, other: (A, B, C, D, E, F, G, H)) -> bool {\n make_tuple_eq_body!(8u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq> Eq for (A, B, C, D, E, F, G, H, I) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I)) -> bool {\n make_tuple_eq_body!(9u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq> Eq for (A, B, C, D, E, F, G, H, I, J) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J)) -> bool {\n make_tuple_eq_body!(10u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> bool {\n make_tuple_eq_body!(11u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq, L: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> bool {\n make_tuple_eq_body!(12u32)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\n/// A value with three states: `Ordering::less()`, `Ordering::equal()` or `Ordering::greater()`.\n/// Most often used to encode the result of a comparison operation.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n/// Compare one object to another, returning whether it is less-than, equal-to,\n/// or greater-than the other object.\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl<T, let N: u32> Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl<T> Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\ncomptime fn make_tuple_ord_body(n: u32) -> Quoted {\n let last = n - 1u32;\n let mut body = if last == 1 {\n f\"let result = self.0.cmp(other.0);\".as_ctstring()\n } else {\n f\"let mut result = self.0.cmp(other.0);\".as_ctstring()\n };\n for i in 1u32..last {\n body = body.append_fmtstr(\n f\" if result == Ordering::equal() {{ result = self.{i}.cmp(other.{i}); }}\",\n );\n }\n body = body.append_fmtstr(\n f\" if result != Ordering::equal() {{ result }} else {{ self.{last}.cmp(other.{last}) }}\",\n );\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Ord, B: Ord> Ord for (A, B) {\n fn cmp(self, other: (A, B)) -> Ordering {\n make_tuple_ord_body!(2u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord> Ord for (A, B, C) {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n make_tuple_ord_body!(3u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord> Ord for (A, B, C, D) {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n make_tuple_ord_body!(4u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord> Ord for (A, B, C, D, E) {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n make_tuple_ord_body!(5u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord> Ord for (A, B, C, D, E, F) {\n fn cmp(self, other: (A, B, C, D, E, F)) -> Ordering {\n make_tuple_ord_body!(6u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord> Ord for (A, B, C, D, E, F, G) {\n fn cmp(self, other: (A, B, C, D, E, F, G)) -> Ordering {\n make_tuple_ord_body!(7u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord> Ord for (A, B, C, D, E, F, G, H) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H)) -> Ordering {\n make_tuple_ord_body!(8u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord> Ord for (A, B, C, D, E, F, G, H, I) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I)) -> Ordering {\n make_tuple_ord_body!(9u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord> Ord for (A, B, C, D, E, F, G, H, I, J) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J)) -> Ordering {\n make_tuple_ord_body!(10u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> Ordering {\n make_tuple_ord_body!(11u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord, L: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> Ordering {\n make_tuple_ord_body!(12u32)\n }\n}\n\n/// Compares and returns the maximum of two values.\n///\n/// Returns the second argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::max(1, 2), 2);\n/// assert_eq(cmp::max(2, 2), 2);\n/// ```\npub fn max<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n/// Compares and returns the minimum of two values.\n///\n/// Returns the first argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::min(1, 2), 1);\n/// assert_eq(cmp::min(2, 2), 2);\n/// ```\npub fn min<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_vectors() {\n let vector_1 = [0, 1, 2, 3].as_vector();\n let vector_2 = [0, 1, 2].as_vector();\n assert(!vector_1.eq(vector_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_vectors() {\n assert(\n [2_u32].as_vector().cmp([1_u32, 1_u32, 1_u32].as_vector())\n == super::Ordering::greater(),\n );\n assert(\n [1_u32, 2_u32].as_vector().cmp([1_u32, 2_u32, 3_u32].as_vector())\n == super::Ordering::less(),\n );\n }\n}\n"
4993
4895
  },
4994
4896
  "50": {
4995
4897
  "function_locations": [
@@ -5003,27 +4905,27 @@
5003
4905
  },
5004
4906
  {
5005
4907
  "name": "ContractInstanceRegistry::update",
5006
- "start": 8454
4908
+ "start": 8513
5007
4909
  },
5008
4910
  {
5009
4911
  "name": "ContractInstanceRegistry::set_update_delay",
5010
- "start": 10748
4912
+ "start": 10807
5011
4913
  },
5012
4914
  {
5013
4915
  "name": "ContractInstanceRegistry::get_update_delay",
5014
- "start": 12051
4916
+ "start": 12110
5015
4917
  },
5016
4918
  {
5017
4919
  "name": "ContractInstanceRegistry::public_dispatch",
5018
- "start": 13211
4920
+ "start": 13270
5019
4921
  },
5020
4922
  {
5021
4923
  "name": "ContractInstanceRegistry::Storage<Context>::init",
5022
- "start": 14376
4924
+ "start": 14435
5023
4925
  }
5024
4926
  ],
5025
4927
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/contract_instance_registry_contract/src/main.nr",
5026
- "source": "/// Protocol contract responsible for deploying contract instances and managing contract upgrades.\n///\n/// In Aztec, contracts are split into *classes* (code, registered via ContractClassRegistry) and *instances*\n/// (deployments of a class at a unique address). This contract handles contract instance publishing and contract\n/// updates (updating instance to a new class).\npub contract ContractInstanceRegistry {\n use aztec::{\n context::{PrivateContext, PublicContext},\n hash::hash_args,\n nullifier::utils::compute_nullifier_existence_request,\n oracle::{avm, logging::debug_log_format, version::assert_compatible_oracle_version},\n protocol::{\n abis::function_selector::FunctionSelector,\n address::{AztecAddress, PartialAddress},\n constants::{\n CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS, CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE,\n CONTRACT_INSTANCE_UPDATED_MAGIC_VALUE, DEFAULT_UPDATE_DELAY, MINIMUM_UPDATE_DELAY,\n },\n contract_class_id::ContractClassId,\n public_keys::PublicKeys,\n traits::{Deserialize, Serialize, ToField},\n utils::reader::Reader,\n },\n state_vars::{DelayedPublicMutable, Map, StateVariable},\n };\n\n #[abi(events)]\n struct ContractInstancePublished {\n CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE: Field,\n address: AztecAddress,\n version: u8,\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys: PublicKeys,\n deployer: AztecAddress,\n }\n\n // Custom serialization is required because we don't want to waste one field for the `is_infinite` flag of public\n // key points (public key points will never be the infinity point).\n impl ContractInstancePublished {\n fn serialize_non_standard(self) -> [Field; 15] {\n [\n self.CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE,\n self.address.to_field(),\n self.version.to_field(),\n self.salt,\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys.npk_m.serialize()[0],\n self.public_keys.npk_m.serialize()[1],\n self.public_keys.ivpk_m.serialize()[0],\n self.public_keys.ivpk_m.serialize()[1],\n self.public_keys.ovpk_m.serialize()[0],\n self.public_keys.ovpk_m.serialize()[1],\n self.public_keys.tpk_m.serialize()[0],\n self.public_keys.tpk_m.serialize()[1],\n self.deployer.to_field(),\n ]\n }\n }\n\n #[abi(events)]\n #[derive(Serialize)]\n struct ContractInstanceUpdated {\n CONTRACT_INSTANCE_UPDATED_MAGIC_VALUE: Field,\n address: AztecAddress,\n prev_contract_class_id: ContractClassId,\n new_contract_class_id: ContractClassId,\n timestamp_of_change: u64,\n }\n\n struct Storage<Context> {\n /// Map from contract instance address to a `DelayedPublicMutable` holding the updated contract class ID.\n updated_class_ids: Map<AztecAddress, DelayedPublicMutable<ContractClassId, DEFAULT_UPDATE_DELAY, Context>, Context>,\n }\n\n /// Publishes a new contract instance.\n ///\n /// The caller provides deployment parameters (salt, class_id, init_hash, public_keys, universal_deploy).\n /// The `universal_deploy` flag controls whether the deployer address is bound into the contract address:\n /// when true, deployer is zero (anyone can deploy the same instance); when false, deployer is the caller.\n ///\n /// This function:\n /// 1. Verifies the contract class is registered in ContractClassRegistry (nullifier existence check).\n /// 2. Validates public key points are on the Grumpkin curve (preventing AVM DoS via invalid points).\n /// 3. Computes the deterministic contract address from the deployment parameters.\n /// 4. Emits the address as a nullifier (proving publication preventing duplicate deployment)\n /// --> this address nullifier is then checked to exist by the AVM upon public function execution (if it doesn't\n /// exist AVM reverts)\n /// 5. Broadcasts a `ContractInstancePublished` event so nodes can reconstruct the instance.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_private]\n fn publish_for_public_execution(\n inputs: aztec::context::inputs::PrivateContextInputs,\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys: PublicKeys,\n universal_deploy: bool,\n ) -> return_data aztec::protocol::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {\n // MACRO CODE START\n // Note: The macros initially inserted a phase check here, but since there is no phase change in this function\n // body, I have removed that check.\n assert_compatible_oracle_version();\n\n let serialized_params: [Field; 16] = [\n salt,\n contract_class_id.to_field(),\n initialization_hash,\n ]\n .concat(public_keys.serialize())\n .concat([universal_deploy.to_field()]);\n\n let args_hash: Field = hash_args(serialized_params);\n let mut context: PrivateContext = PrivateContext::new(inputs, args_hash);\n // MACRO CODE END\n\n // Verify the contract class is registered by checking for its nullifier at the ContractClassRegistry address.\n let nullifier_existence_request = compute_nullifier_existence_request(\n contract_class_id.to_field(),\n CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS,\n );\n context.assert_nullifier_exists(nullifier_existence_request);\n\n // For universal deployments, deployer is zero so the resulting address is the same regardless of who initiates\n // deployment.\n let deployer = if universal_deploy {\n AztecAddress::zero()\n } else {\n context.maybe_msg_sender().unwrap()\n };\n\n let partial_address =\n PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer);\n\n // Validate public key points lie on the Grumpkin curve to prevent AVM DoS attacks.\n public_keys.validate_on_curve();\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // Emit address as nullifier: prevents duplicate deployment and proves publication.\n // We use no domain separators because these are the only nullifiers this contract uses.\n context.push_nullifier(address.to_field());\n\n // Broadcast deployment event. Uses non-standard serialization (2 fields per point,\n // omitting is_infinite) for TypeScript SDK compatibility.\n let event = ContractInstancePublished {\n CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE,\n contract_class_id,\n address,\n public_keys,\n initialization_hash,\n salt,\n deployer,\n version: 1,\n };\n let payload = event.serialize_non_standard();\n debug_log_format(\"ContractInstancePublished: {}\", payload);\n // We pad the payload with [0] to match the length required by emit_private_log. Since the log is not\n // encrypted, padding with zero rather than a random value is acceptable (we don't care about privacy here).\n let padded_log = payload.concat([0]);\n let length = payload.len();\n context.emit_private_log(padded_log, length);\n\n // MACRO CODE START\n context.finish()\n // MACRO CODE END\n }\n\n /// Schedules an upgrade of the calling contract instance to a new contract class.\n ///\n /// The change is time-delayed via `DelayedPublicMutable` and only takes effect after the configured\n /// delay has elapsed. Only the contract instance itself can call this function (msg.sender == address).\n ///\n /// This function:\n /// 1. Verifies msg.sender is a deployed contract (its address nullifier exists).\n /// 2. Verifies the new class is registered in ContractClassRegistry.\n /// 3. Schedules the class ID change and emits a `ContractInstanceUpdated` event.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n unconstrained fn update(new_contract_class_id: ContractClassId) {\n // MACRO CODE START\n let context: PublicContext = PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 1] =\n avm::calldata_copy(1, <ContractClassId as Serialize>::N);\n hash_args(serialized_args)\n },\n );\n let storage: Storage<PublicContext> = Storage::init(context);\n // MACRO CODE END\n\n let address = context.maybe_msg_sender().unwrap();\n\n // Safety: we're using the nullifier's existence as a guarantee of the availability of the contract's\n // information through publishing, which is safe - we just need this information to be _eventually_ available.\n assert(\n context.nullifier_exists_unsafe(address.to_field(), context.this_address()),\n \"msg.sender is not deployed\",\n );\n\n // Safety: we're using the nullifier's existence as a guarantee of the availability of the new contract class'\n // information through registration, which is safe - we just need this information to be _eventually_ available.\n assert(\n context.nullifier_exists_unsafe(\n new_contract_class_id.to_field(),\n CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS,\n ),\n \"New contract class is not registered\",\n );\n\n let scheduled_value_update = storage\n .updated_class_ids\n .at(address)\n .schedule_and_get_value_change(new_contract_class_id);\n let (prev_contract_class_id, timestamp_of_change) = scheduled_value_update.get_previous();\n\n let event = ContractInstanceUpdated {\n CONTRACT_INSTANCE_UPDATED_MAGIC_VALUE,\n address,\n prev_contract_class_id,\n new_contract_class_id,\n timestamp_of_change,\n };\n context.emit_public_log(event);\n }\n\n /// Schedules a change to the upgrade delay for the calling contract instance. The delay change is\n /// itself delayed (preventing atomically reducing delay + scheduling an instant upgrade). The new\n /// delay must be at least `MINIMUM_UPDATE_DELAY`.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n unconstrained fn set_update_delay(new_update_delay: u64) {\n // MACRO CODE START\n let context: PublicContext = PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 1] = avm::calldata_copy(1, <u64 as Serialize>::N);\n hash_args(serialized_args)\n },\n );\n let storage: Storage<PublicContext> = Storage::init(context);\n // MACRO CODE END\n\n let msg_sender = context.maybe_msg_sender().unwrap();\n\n // Safety: we're using the nullifier's existence as a guarantee of the availability of the contract's\n // information through publishing, which is safe - we just need this information to be _eventually_ available.\n assert(\n context.nullifier_exists_unsafe(msg_sender.to_field(), context.this_address()),\n \"msg.sender is not deployed\",\n );\n\n assert(new_update_delay >= MINIMUM_UPDATE_DELAY, \"New update delay is too low\");\n\n storage.updated_class_ids.at(msg_sender).schedule_delay_change(new_update_delay);\n }\n\n /// Returns the current update delay for the calling contract instance.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_view]\n unconstrained fn get_update_delay() -> pub u64 {\n // MACRO CODE START\n let context: PublicContext = PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 0] = avm::calldata_copy(1, 0);\n hash_args(serialized_args)\n },\n );\n let storage: Storage<PublicContext> = Storage::init(context);\n assert(context.is_static_call(), \"Function get_update_delay can only be called statically\");\n // MACRO CODE END\n\n storage.updated_class_ids.at(avm::sender()).get_current_delay()\n }\n\n // THE REST OF THE CODE IN THIS CONTRACT WAS ORIGINALLY INJECTED BY THE #[aztec] MACRO.\n\n global UPDATE_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"update((Field))\").to_field() };\n global SET_UPDATE_DELAY_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"set_update_delay(u64)\").to_field() };\n global GET_UPDATE_DELAY_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"get_update_delay()\").to_field() };\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n pub unconstrained fn public_dispatch(selector: Field) {\n if selector == UPDATE_SELECTOR {\n let input_calldata: [Field; 1] =\n avm::calldata_copy(1, <ContractClassId as Serialize>::N);\n let mut reader: Reader<1> = Reader::new(input_calldata);\n let arg0: ContractClassId =\n <ContractClassId as Deserialize>::stream_deserialize(&mut reader);\n update(arg0);\n avm::avm_return([].as_vector());\n };\n if selector == SET_UPDATE_DELAY_SELECTOR {\n let input_calldata: [Field; 1] = avm::calldata_copy(1, <u64 as Serialize>::N);\n let mut reader: Reader<1> = Reader::new(input_calldata);\n let arg0: u64 = <u64 as Deserialize>::stream_deserialize(&mut reader);\n set_update_delay(arg0);\n avm::avm_return([].as_vector());\n };\n if selector == GET_UPDATE_DELAY_SELECTOR {\n let return_value: [Field; 1] = <u64 as Serialize>::serialize(get_update_delay());\n avm::avm_return(return_value.as_vector());\n };\n panic(f\"Unknown selector {selector}\")\n }\n\n impl<Context> Storage<Context> {\n fn init(context: Context) -> Self {\n Self {\n updated_class_ids: <Map<AztecAddress, DelayedPublicMutable<ContractClassId, DEFAULT_UPDATE_DELAY, Context>, Context> as StateVariable<1, Context>>::new(\n context,\n 1,\n ),\n }\n }\n }\n\n pub struct publish_for_public_execution_parameters {\n pub _salt: Field,\n pub _contract_class_id: ContractClassId,\n pub _initialization_hash: Field,\n pub _public_keys: PublicKeys,\n pub _universal_deploy: bool,\n }\n\n pub struct update_parameters {\n pub _new_contract_class_id: ContractClassId,\n }\n\n pub struct set_update_delay_parameters {\n pub _new_update_delay: u64,\n }\n\n pub struct get_update_delay_parameters {}\n\n #[abi(functions)]\n pub struct publish_for_public_execution_abi {\n parameters: publish_for_public_execution_parameters,\n }\n\n #[abi(functions)]\n pub struct update_abi {\n parameters: update_parameters,\n }\n\n #[abi(functions)]\n pub struct set_update_delay_abi {\n parameters: set_update_delay_parameters,\n }\n\n #[abi(functions)]\n pub struct get_update_delay_abi {\n parameters: get_update_delay_parameters,\n return_type: u64,\n }\n}\n"
4928
+ "source": "/// Protocol contract responsible for deploying contract instances and managing contract upgrades.\n///\n/// In Aztec, contracts are split into *classes* (code, registered via ContractClassRegistry) and *instances*\n/// (deployments of a class at a unique address). This contract handles contract instance publishing and contract\n/// updates (updating instance to a new class).\npub contract ContractInstanceRegistry {\n use aztec::{\n context::{PrivateContext, PublicContext},\n hash::hash_args,\n nullifier::utils::compute_nullifier_existence_request,\n oracle::{avm, logging::debug_log_format, version::assert_compatible_oracle_version},\n protocol::{\n abis::function_selector::FunctionSelector,\n address::{AztecAddress, PartialAddress},\n constants::{\n CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS, CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE,\n CONTRACT_INSTANCE_UPDATED_MAGIC_VALUE, DEFAULT_UPDATE_DELAY, MINIMUM_UPDATE_DELAY,\n },\n contract_class_id::ContractClassId,\n public_keys::PublicKeys,\n traits::{Deserialize, Serialize, ToField},\n utils::reader::Reader,\n },\n state_vars::{DelayedPublicMutable, Map, StateVariable},\n };\n\n #[abi(events)]\n struct ContractInstancePublished {\n CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE: Field,\n address: AztecAddress,\n version: u8,\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys: PublicKeys,\n deployer: AztecAddress,\n }\n\n // Custom serialization is required because we don't want to waste one field for the `is_infinite` flag of public\n // key points (public key points will never be the infinity point).\n impl ContractInstancePublished {\n fn serialize_non_standard(self) -> [Field; 15] {\n [\n self.CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE,\n self.address.to_field(),\n self.version.to_field(),\n self.salt,\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys.npk_m.serialize()[0],\n self.public_keys.npk_m.serialize()[1],\n self.public_keys.ivpk_m.serialize()[0],\n self.public_keys.ivpk_m.serialize()[1],\n self.public_keys.ovpk_m.serialize()[0],\n self.public_keys.ovpk_m.serialize()[1],\n self.public_keys.tpk_m.serialize()[0],\n self.public_keys.tpk_m.serialize()[1],\n self.deployer.to_field(),\n ]\n }\n }\n\n #[abi(events)]\n #[derive(Serialize)]\n struct ContractInstanceUpdated {\n CONTRACT_INSTANCE_UPDATED_MAGIC_VALUE: Field,\n address: AztecAddress,\n prev_contract_class_id: ContractClassId,\n new_contract_class_id: ContractClassId,\n timestamp_of_change: u64,\n }\n\n struct Storage<Context> {\n /// Map from contract instance address to a `DelayedPublicMutable` holding the updated contract class ID.\n updated_class_ids: Map<AztecAddress, DelayedPublicMutable<ContractClassId, DEFAULT_UPDATE_DELAY, Context>, Context>,\n }\n\n /// Publishes a new contract instance.\n ///\n /// The caller provides deployment parameters (salt, class_id, init_hash, public_keys, universal_deploy).\n /// The `universal_deploy` flag controls whether the deployer address is bound into the contract address:\n /// when true, deployer is zero (anyone can deploy the same instance); when false, deployer is the caller.\n ///\n /// This function:\n /// 1. Verifies the contract class is registered in ContractClassRegistry (nullifier existence check).\n /// 2. Validates public key points are on the Grumpkin curve (preventing AVM DoS via invalid points).\n /// 3. Computes the deterministic contract address from the deployment parameters.\n /// 4. Emits the address as a nullifier (proving publication preventing duplicate deployment)\n /// --> this address nullifier is then checked to exist by the AVM upon public function execution (if it doesn't\n /// exist AVM reverts)\n /// 5. Broadcasts a `ContractInstancePublished` event so nodes can reconstruct the instance.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_private]\n fn publish_for_public_execution(\n inputs: aztec::context::inputs::PrivateContextInputs,\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys: PublicKeys,\n universal_deploy: bool,\n ) -> return_data aztec::protocol::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {\n // MACRO CODE START\n // Note: The macros initially inserted a phase check here, but since there is no phase change in this function\n // body, I have removed that check.\n assert_compatible_oracle_version();\n\n let serialized_params: [Field; 16] = [\n salt,\n contract_class_id.to_field(),\n initialization_hash,\n ]\n .concat(public_keys.serialize())\n .concat([universal_deploy.to_field()]);\n\n let args_hash: Field = hash_args(serialized_params);\n let mut context: PrivateContext = PrivateContext::new(inputs, args_hash);\n // MACRO CODE END\n\n // Verify the contract class is registered by checking for its nullifier at the ContractClassRegistry address.\n let nullifier_existence_request = compute_nullifier_existence_request(\n contract_class_id.to_field(),\n CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS,\n );\n context.assert_nullifier_exists(nullifier_existence_request);\n\n // For universal deployments, deployer is zero so the resulting address is the same regardless of who initiates\n // deployment.\n let deployer = if universal_deploy {\n AztecAddress::zero()\n } else {\n context.maybe_msg_sender().unwrap()\n };\n\n let partial_address =\n PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer);\n\n // Validate public key points lie on the Grumpkin curve and are non-0 to prevent AVM DoS attacks.\n public_keys.validate_on_curve();\n public_keys.validate_non_infinity();\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // Emit address as nullifier: prevents duplicate deployment and proves publication.\n // We use no domain separators because these are the only nullifiers this contract uses.\n context.push_nullifier(address.to_field());\n\n // Broadcast deployment event. Uses non-standard serialization (2 fields per point,\n // omitting is_infinite) for TypeScript SDK compatibility.\n let event = ContractInstancePublished {\n CONTRACT_INSTANCE_PUBLISHED_MAGIC_VALUE,\n contract_class_id,\n address,\n public_keys,\n initialization_hash,\n salt,\n deployer,\n version: 1,\n };\n let payload = event.serialize_non_standard();\n debug_log_format(\"ContractInstancePublished: {}\", payload);\n // We pad the payload with [0] to match the length required by emit_private_log. Since the log is not\n // encrypted, padding with zero rather than a random value is acceptable (we don't care about privacy here).\n let padded_log = payload.concat([0]);\n let length = payload.len();\n context.emit_private_log(padded_log, length);\n\n // MACRO CODE START\n context.finish()\n // MACRO CODE END\n }\n\n /// Schedules an upgrade of the calling contract instance to a new contract class.\n ///\n /// The change is time-delayed via `DelayedPublicMutable` and only takes effect after the configured\n /// delay has elapsed. Only the contract instance itself can call this function (msg.sender == address).\n ///\n /// This function:\n /// 1. Verifies msg.sender is a deployed contract (its address nullifier exists).\n /// 2. Verifies the new class is registered in ContractClassRegistry.\n /// 3. Schedules the class ID change and emits a `ContractInstanceUpdated` event.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n unconstrained fn update(new_contract_class_id: ContractClassId) {\n // MACRO CODE START\n let context: PublicContext = PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 1] =\n avm::calldata_copy(1, <ContractClassId as Serialize>::N);\n hash_args(serialized_args)\n },\n );\n let storage: Storage<PublicContext> = Storage::init(context);\n // MACRO CODE END\n\n let address = context.maybe_msg_sender().unwrap();\n\n // Safety: we're using the nullifier's existence as a guarantee of the availability of the contract's\n // information through publishing, which is safe - we just need this information to be _eventually_ available.\n assert(\n context.nullifier_exists_unsafe(address.to_field(), context.this_address()),\n \"msg.sender is not deployed\",\n );\n\n // Safety: we're using the nullifier's existence as a guarantee of the availability of the new contract class'\n // information through registration, which is safe - we just need this information to be _eventually_ available.\n assert(\n context.nullifier_exists_unsafe(\n new_contract_class_id.to_field(),\n CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS,\n ),\n \"New contract class is not registered\",\n );\n\n let scheduled_value_update = storage\n .updated_class_ids\n .at(address)\n .schedule_and_get_value_change(new_contract_class_id);\n let (prev_contract_class_id, timestamp_of_change) = scheduled_value_update.get_previous();\n\n let event = ContractInstanceUpdated {\n CONTRACT_INSTANCE_UPDATED_MAGIC_VALUE,\n address,\n prev_contract_class_id,\n new_contract_class_id,\n timestamp_of_change,\n };\n context.emit_public_log(event);\n }\n\n /// Schedules a change to the upgrade delay for the calling contract instance. The delay change is\n /// itself delayed (preventing atomically reducing delay + scheduling an instant upgrade). The new\n /// delay must be at least `MINIMUM_UPDATE_DELAY`.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n unconstrained fn set_update_delay(new_update_delay: u64) {\n // MACRO CODE START\n let context: PublicContext = PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 1] = avm::calldata_copy(1, <u64 as Serialize>::N);\n hash_args(serialized_args)\n },\n );\n let storage: Storage<PublicContext> = Storage::init(context);\n // MACRO CODE END\n\n let msg_sender = context.maybe_msg_sender().unwrap();\n\n // Safety: we're using the nullifier's existence as a guarantee of the availability of the contract's\n // information through publishing, which is safe - we just need this information to be _eventually_ available.\n assert(\n context.nullifier_exists_unsafe(msg_sender.to_field(), context.this_address()),\n \"msg.sender is not deployed\",\n );\n\n assert(new_update_delay >= MINIMUM_UPDATE_DELAY, \"New update delay is too low\");\n\n storage.updated_class_ids.at(msg_sender).schedule_delay_change(new_update_delay);\n }\n\n /// Returns the current update delay for the calling contract instance.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_view]\n unconstrained fn get_update_delay() -> pub u64 {\n // MACRO CODE START\n let context: PublicContext = PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 0] = avm::calldata_copy(1, 0);\n hash_args(serialized_args)\n },\n );\n let storage: Storage<PublicContext> = Storage::init(context);\n assert(context.is_static_call(), \"Function get_update_delay can only be called statically\");\n // MACRO CODE END\n\n storage.updated_class_ids.at(avm::sender()).get_current_delay()\n }\n\n // THE REST OF THE CODE IN THIS CONTRACT WAS ORIGINALLY INJECTED BY THE #[aztec] MACRO.\n\n global UPDATE_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"update((Field))\").to_field() };\n global SET_UPDATE_DELAY_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"set_update_delay(u64)\").to_field() };\n global GET_UPDATE_DELAY_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"get_update_delay()\").to_field() };\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n pub unconstrained fn public_dispatch(selector: Field) {\n if selector == UPDATE_SELECTOR {\n let input_calldata: [Field; 1] =\n avm::calldata_copy(1, <ContractClassId as Serialize>::N);\n let mut reader: Reader<1> = Reader::new(input_calldata);\n let arg0: ContractClassId =\n <ContractClassId as Deserialize>::stream_deserialize(&mut reader);\n update(arg0);\n avm::avm_return([].as_vector());\n };\n if selector == SET_UPDATE_DELAY_SELECTOR {\n let input_calldata: [Field; 1] = avm::calldata_copy(1, <u64 as Serialize>::N);\n let mut reader: Reader<1> = Reader::new(input_calldata);\n let arg0: u64 = <u64 as Deserialize>::stream_deserialize(&mut reader);\n set_update_delay(arg0);\n avm::avm_return([].as_vector());\n };\n if selector == GET_UPDATE_DELAY_SELECTOR {\n let return_value: [Field; 1] = <u64 as Serialize>::serialize(get_update_delay());\n avm::avm_return(return_value.as_vector());\n };\n panic(f\"Unknown selector {selector}\")\n }\n\n impl<Context> Storage<Context> {\n fn init(context: Context) -> Self {\n Self {\n updated_class_ids: <Map<AztecAddress, DelayedPublicMutable<ContractClassId, DEFAULT_UPDATE_DELAY, Context>, Context> as StateVariable<1, Context>>::new(\n context,\n 1,\n ),\n }\n }\n }\n\n pub struct publish_for_public_execution_parameters {\n pub _salt: Field,\n pub _contract_class_id: ContractClassId,\n pub _initialization_hash: Field,\n pub _public_keys: PublicKeys,\n pub _universal_deploy: bool,\n }\n\n pub struct update_parameters {\n pub _new_contract_class_id: ContractClassId,\n }\n\n pub struct set_update_delay_parameters {\n pub _new_update_delay: u64,\n }\n\n pub struct get_update_delay_parameters {}\n\n #[abi(functions)]\n pub struct publish_for_public_execution_abi {\n parameters: publish_for_public_execution_parameters,\n }\n\n #[abi(functions)]\n pub struct update_abi {\n parameters: update_parameters,\n }\n\n #[abi(functions)]\n pub struct set_update_delay_abi {\n parameters: set_update_delay_parameters,\n }\n\n #[abi(functions)]\n pub struct get_update_delay_abi {\n parameters: get_update_delay_parameters,\n return_type: u64,\n }\n}\n"
5027
4929
  },
5028
4930
  "57": {
5029
4931
  "function_locations": [
@@ -5147,115 +5049,115 @@
5147
5049
  },
5148
5050
  {
5149
5051
  "name": "PublicContext::l1_to_l2_msg_exists",
5150
- "start": 1791
5052
+ "start": 1786
5151
5053
  },
5152
5054
  {
5153
5055
  "name": "PublicContext::nullifier_exists_unsafe",
5154
- "start": 2236
5056
+ "start": 2226
5155
5057
  },
5156
5058
  {
5157
5059
  "name": "PublicContext::consume_l1_to_l2_message",
5158
- "start": 2700
5060
+ "start": 2685
5159
5061
  },
5160
5062
  {
5161
5063
  "name": "PublicContext::message_portal",
5162
- "start": 3586
5064
+ "start": 3571
5163
5065
  },
5164
5066
  {
5165
5067
  "name": "PublicContext::call_public_function",
5166
- "start": 4011
5068
+ "start": 3996
5167
5069
  },
5168
5070
  {
5169
5071
  "name": "PublicContext::static_call_public_function",
5170
- "start": 4911
5072
+ "start": 4896
5171
5073
  },
5172
5074
  {
5173
5075
  "name": "PublicContext::push_note_hash",
5174
- "start": 5612
5076
+ "start": 5597
5175
5077
  },
5176
5078
  {
5177
5079
  "name": "PublicContext::push_nullifier",
5178
- "start": 5846
5080
+ "start": 5831
5179
5081
  },
5180
5082
  {
5181
5083
  "name": "PublicContext::this_address",
5182
- "start": 6092
5084
+ "start": 6077
5183
5085
  },
5184
5086
  {
5185
5087
  "name": "PublicContext::maybe_msg_sender",
5186
- "start": 6357
5088
+ "start": 6342
5187
5089
  },
5188
5090
  {
5189
5091
  "name": "PublicContext::selector",
5190
- "start": 6779
5092
+ "start": 6764
5191
5093
  },
5192
5094
  {
5193
5095
  "name": "PublicContext::get_args_hash",
5194
- "start": 7212
5096
+ "start": 7197
5195
5097
  },
5196
5098
  {
5197
5099
  "name": "PublicContext::transaction_fee",
5198
- "start": 7500
5100
+ "start": 7485
5199
5101
  },
5200
5102
  {
5201
5103
  "name": "PublicContext::chain_id",
5202
- "start": 7731
5104
+ "start": 7716
5203
5105
  },
5204
5106
  {
5205
5107
  "name": "PublicContext::version",
5206
- "start": 7939
5108
+ "start": 7924
5207
5109
  },
5208
5110
  {
5209
5111
  "name": "PublicContext::block_number",
5210
- "start": 8153
5112
+ "start": 8138
5211
5113
  },
5212
5114
  {
5213
5115
  "name": "PublicContext::timestamp",
5214
- "start": 8379
5116
+ "start": 8364
5215
5117
  },
5216
5118
  {
5217
5119
  "name": "PublicContext::min_fee_per_l2_gas",
5218
- "start": 8604
5120
+ "start": 8589
5219
5121
  },
5220
5122
  {
5221
5123
  "name": "PublicContext::min_fee_per_da_gas",
5222
- "start": 8838
5124
+ "start": 8823
5223
5125
  },
5224
5126
  {
5225
5127
  "name": "PublicContext::l2_gas_left",
5226
- "start": 9068
5128
+ "start": 9053
5227
5129
  },
5228
5130
  {
5229
5131
  "name": "PublicContext::da_gas_left",
5230
- "start": 9291
5132
+ "start": 9276
5231
5133
  },
5232
5134
  {
5233
5135
  "name": "PublicContext::is_static_call",
5234
- "start": 9542
5136
+ "start": 9527
5235
5137
  },
5236
5138
  {
5237
5139
  "name": "PublicContext::raw_storage_read",
5238
- "start": 9801
5140
+ "start": 9781
5239
5141
  },
5240
5142
  {
5241
5143
  "name": "PublicContext::storage_read",
5242
- "start": 10236
5144
+ "start": 10216
5243
5145
  },
5244
5146
  {
5245
5147
  "name": "PublicContext::raw_storage_write",
5246
- "start": 10446
5148
+ "start": 10426
5247
5149
  },
5248
5150
  {
5249
5151
  "name": "PublicContext::storage_write",
5250
- "start": 10787
5152
+ "start": 10767
5251
5153
  },
5252
5154
  {
5253
5155
  "name": "<impl Empty for PublicContext>::empty",
5254
- "start": 10912
5156
+ "start": 10892
5255
5157
  }
5256
5158
  ],
5257
5159
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/context/public_context.nr",
5258
- "source": "use crate::{\n context::gas::GasOpts,\n hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n compute_siloed_nullifier,\n },\n oracle::avm,\n};\nuse crate::protocol::{\n abis::function_selector::FunctionSelector,\n address::{AztecAddress, EthAddress},\n constants::{MAX_U32_VALUE, NULL_MSG_SENDER_CONTRACT_ADDRESS},\n traits::{Empty, FromField, Packable, Serialize, ToField},\n};\n\n/// Minimal PublicContext for protocol contracts going to audit.\npub struct PublicContext {\n pub args_hash: Option<Field>,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n pub fn emit_public_log<T>(_self: Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_public_log(Serialize::serialize(log).as_vector()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular leaf_index.\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::note_hash_exists(note_hash, leaf_index) } == 1\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message tree at a particular leaf index.\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { avm::l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) } == 1\n }\n\n /// Returns `true` if an `unsiloed_nullifier` has been emitted by `contract_address`.\n pub fn nullifier_exists_unsafe(\n _self: Self,\n unsiloed_nullifier: Field,\n contract_address: AztecAddress,\n ) -> bool {\n let siloed_nullifier = compute_siloed_nullifier(contract_address, unsiloed_nullifier);\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::nullifier_exists(siloed_nullifier) } == 1\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2).\n pub fn consume_l1_to_l2_message(\n self: Self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists_unsafe(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\".\n pub fn message_portal(_self: Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n pub unconstrained fn call_public_function<let N: u32>(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n avm::call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = avm::success_copy();\n\n let result_data = avm::returndata_copy(0, avm::returndata_size());\n if !success {\n // Rethrow the revert data.\n avm::revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n pub unconstrained fn static_call_public_function<let N: u32>(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n avm::call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = avm::success_copy();\n\n let result_data = avm::returndata_copy(0, avm::returndata_size());\n if !success {\n // Rethrow the revert data.\n avm::revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Note Hash Tree.\n pub fn push_note_hash(_self: Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Nullifier Tree.\n pub fn push_nullifier(_self: Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n pub fn maybe_msg_sender(_self: Self) -> Option<AztecAddress> {\n // Safety: AVM opcodes are constrained by the AVM itself\n let maybe_msg_sender = unsafe { avm::sender() };\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself.\n let raw_selector: [Field; 1] = unsafe { avm::calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::chain_id()\n }\n }\n\n /// Returns the protocol version.\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::version()\n }\n }\n\n /// Returns the current block number.\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas.\n pub fn min_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::min_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA gas.\n pub fn min_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::min_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available.\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::l2_gas_left()\n }\n }\n\n /// Returns the remaining DA gas available.\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context.\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::is_static_call() } == 1\n }\n\n /// Reads raw field values from public storage.\n pub fn raw_storage_read<let N: u32>(self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe {\n avm::storage_read(storage_slot + i as Field, self.this_address().to_field())\n };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n pub fn storage_read<T>(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n pub fn raw_storage_write<let N: u32>(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n pub fn storage_write<T>(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n"
5160
+ "source": "use crate::{\n context::gas::GasOpts,\n hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n compute_siloed_nullifier,\n },\n oracle::avm,\n};\nuse crate::protocol::{\n abis::function_selector::FunctionSelector,\n address::{AztecAddress, EthAddress},\n constants::{MAX_U32_VALUE, NULL_MSG_SENDER_CONTRACT_ADDRESS},\n traits::{Empty, FromField, Packable, Serialize, ToField},\n};\n\n/// Minimal PublicContext for protocol contracts going to audit.\npub struct PublicContext {\n pub args_hash: Option<Field>,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n pub fn emit_public_log<T>(_self: Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_public_log(Serialize::serialize(log).as_vector()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular leaf_index.\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::note_hash_exists(note_hash, leaf_index) }\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message tree at a particular leaf index.\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { avm::l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) }\n }\n\n /// Returns `true` if an `unsiloed_nullifier` has been emitted by `contract_address`.\n pub fn nullifier_exists_unsafe(\n _self: Self,\n unsiloed_nullifier: Field,\n contract_address: AztecAddress,\n ) -> bool {\n let siloed_nullifier = compute_siloed_nullifier(contract_address, unsiloed_nullifier);\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::nullifier_exists(siloed_nullifier) }\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2).\n pub fn consume_l1_to_l2_message(\n self: Self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists_unsafe(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\".\n pub fn message_portal(_self: Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n pub unconstrained fn call_public_function<let N: u32>(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n avm::call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = avm::success_copy();\n\n let result_data = avm::returndata_copy(0, avm::returndata_size());\n if !success {\n // Rethrow the revert data.\n avm::revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n pub unconstrained fn static_call_public_function<let N: u32>(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n avm::call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = avm::success_copy();\n\n let result_data = avm::returndata_copy(0, avm::returndata_size());\n if !success {\n // Rethrow the revert data.\n avm::revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Note Hash Tree.\n pub fn push_note_hash(_self: Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Nullifier Tree.\n pub fn push_nullifier(_self: Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n pub fn maybe_msg_sender(_self: Self) -> Option<AztecAddress> {\n // Safety: AVM opcodes are constrained by the AVM itself\n let maybe_msg_sender = unsafe { avm::sender() };\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself.\n let raw_selector: [Field; 1] = unsafe { avm::calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::chain_id()\n }\n }\n\n /// Returns the protocol version.\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::version()\n }\n }\n\n /// Returns the current block number.\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas.\n pub fn min_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::min_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA gas.\n pub fn min_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::min_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available.\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::l2_gas_left()\n }\n }\n\n /// Returns the remaining DA gas available.\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context.\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::is_static_call() }\n }\n\n /// Reads raw field values from public storage.\n pub fn raw_storage_read<let N: u32>(self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe {\n avm::storage_read(storage_slot + i as Field, self.this_address().to_field())\n };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n pub fn storage_read<T>(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n pub fn raw_storage_write<let N: u32>(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n pub fn storage_write<T>(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n"
5259
5161
  },
5260
5162
  "61": {
5261
5163
  "function_locations": [
@@ -5345,195 +5247,195 @@
5345
5247
  },
5346
5248
  {
5347
5249
  "name": "is_static_call",
5348
- "start": 1078
5250
+ "start": 1080
5349
5251
  },
5350
5252
  {
5351
5253
  "name": "note_hash_exists",
5352
- "start": 1189
5254
+ "start": 1193
5353
5255
  },
5354
5256
  {
5355
5257
  "name": "emit_note_hash",
5356
- "start": 1298
5258
+ "start": 1302
5357
5259
  },
5358
5260
  {
5359
5261
  "name": "nullifier_exists",
5360
- "start": 1408
5262
+ "start": 1414
5361
5263
  },
5362
5264
  {
5363
5265
  "name": "emit_nullifier",
5364
- "start": 1512
5266
+ "start": 1518
5365
5267
  },
5366
5268
  {
5367
5269
  "name": "emit_public_log",
5368
- "start": 1608
5270
+ "start": 1614
5369
5271
  },
5370
5272
  {
5371
5273
  "name": "l1_to_l2_msg_exists",
5372
- "start": 1733
5274
+ "start": 1741
5373
5275
  },
5374
5276
  {
5375
5277
  "name": "send_l2_to_l1_msg",
5376
- "start": 1872
5278
+ "start": 1880
5377
5279
  },
5378
5280
  {
5379
5281
  "name": "call",
5380
- "start": 2072
5282
+ "start": 2080
5381
5283
  },
5382
5284
  {
5383
5285
  "name": "call_static",
5384
- "start": 2302
5286
+ "start": 2310
5385
5287
  },
5386
5288
  {
5387
5289
  "name": "calldata_copy",
5388
- "start": 2478
5290
+ "start": 2486
5389
5291
  },
5390
5292
  {
5391
5293
  "name": "success_copy",
5392
- "start": 2661
5294
+ "start": 2669
5393
5295
  },
5394
5296
  {
5395
5297
  "name": "returndata_size",
5396
- "start": 2738
5298
+ "start": 2746
5397
5299
  },
5398
5300
  {
5399
5301
  "name": "returndata_copy",
5400
- "start": 2851
5302
+ "start": 2859
5401
5303
  },
5402
5304
  {
5403
5305
  "name": "avm_return",
5404
- "start": 3036
5306
+ "start": 3044
5405
5307
  },
5406
5308
  {
5407
5309
  "name": "revert",
5408
- "start": 3413
5310
+ "start": 3421
5409
5311
  },
5410
5312
  {
5411
5313
  "name": "storage_read",
5412
- "start": 3537
5314
+ "start": 3545
5413
5315
  },
5414
5316
  {
5415
5317
  "name": "storage_write",
5416
- "start": 3668
5318
+ "start": 3676
5417
5319
  },
5418
5320
  {
5419
5321
  "name": "address_opcode",
5420
- "start": 3799
5322
+ "start": 3807
5421
5323
  },
5422
5324
  {
5423
5325
  "name": "sender_opcode",
5424
- "start": 3880
5326
+ "start": 3888
5425
5327
  },
5426
5328
  {
5427
5329
  "name": "transaction_fee_opcode",
5428
- "start": 3971
5330
+ "start": 3979
5429
5331
  },
5430
5332
  {
5431
5333
  "name": "chain_id_opcode",
5432
- "start": 4048
5334
+ "start": 4056
5433
5335
  },
5434
5336
  {
5435
5337
  "name": "version_opcode",
5436
- "start": 4124
5338
+ "start": 4132
5437
5339
  },
5438
5340
  {
5439
5341
  "name": "block_number_opcode",
5440
- "start": 4207
5342
+ "start": 4215
5441
5343
  },
5442
5344
  {
5443
5345
  "name": "timestamp_opcode",
5444
- "start": 4285
5346
+ "start": 4293
5445
5347
  },
5446
5348
  {
5447
5349
  "name": "min_fee_per_l2_gas_opcode",
5448
- "start": 4378
5350
+ "start": 4386
5449
5351
  },
5450
5352
  {
5451
5353
  "name": "min_fee_per_da_gas_opcode",
5452
- "start": 4471
5354
+ "start": 4479
5453
5355
  },
5454
5356
  {
5455
5357
  "name": "l2_gas_left_opcode",
5456
- "start": 4551
5358
+ "start": 4559
5457
5359
  },
5458
5360
  {
5459
5361
  "name": "da_gas_left_opcode",
5460
- "start": 4631
5362
+ "start": 4639
5461
5363
  },
5462
5364
  {
5463
5365
  "name": "is_static_call_opcode",
5464
- "start": 4716
5366
+ "start": 4726
5465
5367
  },
5466
5368
  {
5467
5369
  "name": "note_hash_exists_opcode",
5468
- "start": 4838
5370
+ "start": 4850
5469
5371
  },
5470
5372
  {
5471
5373
  "name": "emit_note_hash_opcode",
5472
- "start": 4933
5374
+ "start": 4945
5473
5375
  },
5474
5376
  {
5475
5377
  "name": "nullifier_exists_opcode",
5476
- "start": 5046
5378
+ "start": 5060
5477
5379
  },
5478
5380
  {
5479
5381
  "name": "emit_nullifier_opcode",
5480
- "start": 5142
5382
+ "start": 5156
5481
5383
  },
5482
5384
  {
5483
5385
  "name": "emit_public_log_opcode",
5484
- "start": 5239
5386
+ "start": 5253
5485
5387
  },
5486
5388
  {
5487
5389
  "name": "l1_to_l2_msg_exists_opcode",
5488
- "start": 5368
5390
+ "start": 5384
5489
5391
  },
5490
5392
  {
5491
5393
  "name": "send_l2_to_l1_msg_opcode",
5492
- "start": 5488
5394
+ "start": 5504
5493
5395
  },
5494
5396
  {
5495
5397
  "name": "calldata_copy_opcode",
5496
- "start": 5621
5398
+ "start": 5637
5497
5399
  },
5498
5400
  {
5499
5401
  "name": "returndata_size_opcode",
5500
- "start": 5710
5402
+ "start": 5726
5501
5403
  },
5502
5404
  {
5503
5405
  "name": "returndata_copy_opcode",
5504
- "start": 5832
5406
+ "start": 5848
5505
5407
  },
5506
5408
  {
5507
5409
  "name": "return_opcode",
5508
- "start": 5916
5410
+ "start": 5932
5509
5411
  },
5510
5412
  {
5511
5413
  "name": "revert_opcode",
5512
- "start": 6000
5414
+ "start": 6016
5513
5415
  },
5514
5416
  {
5515
5417
  "name": "call_opcode",
5516
- "start": 6447
5418
+ "start": 6463
5517
5419
  },
5518
5420
  {
5519
5421
  "name": "call_static_opcode",
5520
- "start": 6907
5422
+ "start": 6923
5521
5423
  },
5522
5424
  {
5523
5425
  "name": "success_copy_opcode",
5524
- "start": 6991
5426
+ "start": 7007
5525
5427
  },
5526
5428
  {
5527
5429
  "name": "storage_read_opcode",
5528
- "start": 7120
5430
+ "start": 7136
5529
5431
  },
5530
5432
  {
5531
5433
  "name": "storage_write_opcode",
5532
- "start": 7231
5434
+ "start": 7247
5533
5435
  }
5534
5436
  ],
5535
5437
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/avm.nr",
5536
- "source": "//! AVM oracles.\n//!\n//! There are only available during public execution. Calling any of them from a private or utility function will\n//! result in runtime errors.\n\nuse crate::protocol::address::{AztecAddress, EthAddress};\n\npub unconstrained fn address() -> AztecAddress {\n address_opcode()\n}\npub unconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\npub unconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\npub unconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\npub unconstrained fn version() -> Field {\n version_opcode()\n}\npub unconstrained fn block_number() -> u32 {\n block_number_opcode()\n}\npub unconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\npub unconstrained fn min_fee_per_l2_gas() -> u128 {\n min_fee_per_l2_gas_opcode()\n}\npub unconstrained fn min_fee_per_da_gas() -> u128 {\n min_fee_per_da_gas_opcode()\n}\npub unconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\npub unconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\npub unconstrained fn is_static_call() -> u1 {\n is_static_call_opcode()\n}\npub unconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> u1 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\npub unconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\npub unconstrained fn nullifier_exists(siloed_nullifier: Field) -> u1 {\n nullifier_exists_opcode(siloed_nullifier)\n}\npub unconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\npub unconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\npub unconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> u1 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\npub unconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\n\npub unconstrained fn call<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn call_static<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn calldata_copy<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n/// `success_copy` is placed immediately after the CALL opcode to get the success value\npub unconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\npub unconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\npub unconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\n/// The additional prefix is to avoid clashing with the `return` Noir keyword.\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n/// This opcode reverts using the exact data given. In general it should only be used to do rethrows, where the revert\n/// data is the same as the original revert data. For normal reverts, use Noir's `assert` which, on top of reverting,\n/// will also add an error selector to the revert data.\npub unconstrained fn revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\npub unconstrained fn storage_read(storage_slot: Field, contract_address: Field) -> Field {\n storage_read_opcode(storage_slot, contract_address)\n}\n\npub unconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\n#[oracle(aztec_avm_address)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(aztec_avm_sender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(aztec_avm_transactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(aztec_avm_chainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(aztec_avm_version)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(aztec_avm_blockNumber)]\nunconstrained fn block_number_opcode() -> u32 {}\n\n#[oracle(aztec_avm_timestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(aztec_avm_minFeePerL2Gas)]\nunconstrained fn min_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(aztec_avm_minFeePerDaGas)]\nunconstrained fn min_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(aztec_avm_l2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(aztec_avm_daGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(aztec_avm_isStaticCall)]\nunconstrained fn is_static_call_opcode() -> u1 {}\n\n#[oracle(aztec_avm_noteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> u1 {}\n\n#[oracle(aztec_avm_emitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(aztec_avm_nullifierExists)]\nunconstrained fn nullifier_exists_opcode(siloed_nullifier: Field) -> u1 {}\n\n#[oracle(aztec_avm_emitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(aztec_avm_emitPublicLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(aztec_avm_l1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> u1 {}\n\n#[oracle(aztec_avm_sendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(aztec_avm_calldataCopy)]\nunconstrained fn calldata_copy_opcode<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(aztec_avm_returndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(aztec_avm_returndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(aztec_avm_return)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n#[oracle(aztec_avm_revert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take\n// that route.\n#[oracle(aztec_avm_call)]\nunconstrained fn call_opcode<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take\n// that route.\n#[oracle(aztec_avm_staticCall)]\nunconstrained fn call_static_opcode<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n#[oracle(aztec_avm_successCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(aztec_avm_storageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field, contract_address: Field) -> Field {}\n\n#[oracle(aztec_avm_storageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n"
5438
+ "source": "//! AVM oracles.\n//!\n//! There are only available during public execution. Calling any of them from a private or utility function will\n//! result in runtime errors.\n\nuse crate::protocol::address::{AztecAddress, EthAddress};\n\npub unconstrained fn address() -> AztecAddress {\n address_opcode()\n}\npub unconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\npub unconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\npub unconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\npub unconstrained fn version() -> Field {\n version_opcode()\n}\npub unconstrained fn block_number() -> u32 {\n block_number_opcode()\n}\npub unconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\npub unconstrained fn min_fee_per_l2_gas() -> u128 {\n min_fee_per_l2_gas_opcode()\n}\npub unconstrained fn min_fee_per_da_gas() -> u128 {\n min_fee_per_da_gas_opcode()\n}\npub unconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\npub unconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\npub unconstrained fn is_static_call() -> bool {\n is_static_call_opcode()\n}\npub unconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> bool {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\npub unconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\npub unconstrained fn nullifier_exists(siloed_nullifier: Field) -> bool {\n nullifier_exists_opcode(siloed_nullifier)\n}\npub unconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\npub unconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\npub unconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> bool {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\npub unconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\n\npub unconstrained fn call<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn call_static<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn calldata_copy<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n/// `success_copy` is placed immediately after the CALL opcode to get the success value\npub unconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\npub unconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\npub unconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\n/// The additional prefix is to avoid clashing with the `return` Noir keyword.\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n/// This opcode reverts using the exact data given. In general it should only be used to do rethrows, where the revert\n/// data is the same as the original revert data. For normal reverts, use Noir's `assert` which, on top of reverting,\n/// will also add an error selector to the revert data.\npub unconstrained fn revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\npub unconstrained fn storage_read(storage_slot: Field, contract_address: Field) -> Field {\n storage_read_opcode(storage_slot, contract_address)\n}\n\npub unconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\n#[oracle(aztec_avm_address)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(aztec_avm_sender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(aztec_avm_transactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(aztec_avm_chainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(aztec_avm_version)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(aztec_avm_blockNumber)]\nunconstrained fn block_number_opcode() -> u32 {}\n\n#[oracle(aztec_avm_timestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(aztec_avm_minFeePerL2Gas)]\nunconstrained fn min_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(aztec_avm_minFeePerDaGas)]\nunconstrained fn min_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(aztec_avm_l2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(aztec_avm_daGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(aztec_avm_isStaticCall)]\nunconstrained fn is_static_call_opcode() -> bool {}\n\n#[oracle(aztec_avm_noteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> bool {}\n\n#[oracle(aztec_avm_emitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(aztec_avm_nullifierExists)]\nunconstrained fn nullifier_exists_opcode(siloed_nullifier: Field) -> bool {}\n\n#[oracle(aztec_avm_emitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(aztec_avm_emitPublicLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(aztec_avm_l1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> bool {}\n\n#[oracle(aztec_avm_sendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(aztec_avm_calldataCopy)]\nunconstrained fn calldata_copy_opcode<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(aztec_avm_returndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(aztec_avm_returndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(aztec_avm_return)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n#[oracle(aztec_avm_revert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take\n// that route.\n#[oracle(aztec_avm_call)]\nunconstrained fn call_opcode<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take\n// that route.\n#[oracle(aztec_avm_staticCall)]\nunconstrained fn call_static_opcode<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n#[oracle(aztec_avm_successCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(aztec_avm_storageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field, contract_address: Field) -> Field {}\n\n#[oracle(aztec_avm_storageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n"
5537
5439
  },
5538
5440
  "79": {
5539
5441
  "function_locations": [
@@ -5569,27 +5471,27 @@
5569
5471
  "function_locations": [
5570
5472
  {
5571
5473
  "name": "assert_compatible_oracle_version",
5572
- "start": 700
5474
+ "start": 1191
5573
5475
  },
5574
5476
  {
5575
5477
  "name": "assert_compatible_oracle_version_wrapper",
5576
- "start": 1009
5478
+ "start": 1500
5577
5479
  },
5578
5480
  {
5579
5481
  "name": "assert_compatible_oracle_version_oracle",
5580
- "start": 1199
5482
+ "start": 1732
5581
5483
  },
5582
5484
  {
5583
5485
  "name": "test::compatible_oracle_version",
5584
- "start": 1350
5486
+ "start": 1926
5585
5487
  },
5586
5488
  {
5587
- "name": "test::incompatible_oracle_version",
5588
- "start": 1541
5489
+ "name": "test::incompatible_oracle_version_major",
5490
+ "start": 2151
5589
5491
  }
5590
5492
  ],
5591
5493
  "path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/version.nr",
5592
- "source": "/// The ORACLE_VERSION constant is used to check that the oracle interface is in sync between PXE and Aztec.nr. We need\n/// to version the oracle interface to ensure that developers get a reasonable error message if they use incompatible\n/// versions of Aztec.nr and PXE. The TypeScript counterpart is in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `aztec_utl_assertCompatibleOracleVersion` oracle is\n/// called and if the oracle version is incompatible an error is thrown.\npub global ORACLE_VERSION: Field = 22;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n}\n\n#[oracle(aztec_utl_assertCompatibleOracleVersion)]\nunconstrained fn assert_compatible_oracle_version_oracle(version: Field) {}\n\nmod test {\n use super::{assert_compatible_oracle_version_oracle, ORACLE_VERSION};\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n }\n\n #[test(should_fail_with = \"Incompatible aztec cli version:\")]\n unconstrained fn incompatible_oracle_version() {\n let arbitrary_incorrect_version = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_version);\n }\n}\n"
5494
+ "source": "/// The oracle version constants are used to check that the oracle interface is in sync between PXE and Aztec.nr.\n/// We version the oracle interface as `major.minor` where:\n/// - `major` = backward-breaking changes (must match exactly between PXE and Aztec.nr)\n/// - `minor` = oracle additions (non-breaking; PXE minor >= contract minor)\n///\n/// The TypeScript counterparts are in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `aztec_utl_assertCompatibleOracleVersion` oracle is\n/// called. If the major version is incompatible, an error is thrown immediately. The minor version is recorded by\n/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw\n/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency\n/// without actually using any of the new oracles then there is no reason to throw.\npub global ORACLE_VERSION_MAJOR: Field = 22;\npub global ORACLE_VERSION_MINOR: Field = 1;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR);\n}\n\n#[oracle(aztec_utl_assertCompatibleOracleVersionV2)]\nunconstrained fn assert_compatible_oracle_version_oracle(major: Field, minor: Field) {}\n\nmod test {\n use super::{\n assert_compatible_oracle_version_oracle, ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR,\n };\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR);\n }\n\n #[test(should_fail_with = \"Incompatible aztec cli version:\")]\n unconstrained fn incompatible_oracle_version_major() {\n let arbitrary_incorrect_major = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_major, ORACLE_VERSION_MINOR);\n }\n}\n"
5593
5495
  },
5594
5496
  "84": {
5595
5497
  "function_locations": [