@aztec/protocol-contracts 0.0.1-commit.ff7989d6c → 0.0.1-commit.fff30aa
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.
- package/artifacts/AuthRegistry.json +235 -1004
- package/artifacts/ContractClassRegistry.json +9 -9
- package/artifacts/ContractInstanceRegistry.json +21 -17
- package/artifacts/FeeJuice.json +17 -17
- package/artifacts/MultiCallEntrypoint.json +17 -25
- package/artifacts/PublicChecks.json +23 -31
- package/dest/class-registry/contract_class_published_event.d.ts +6 -3
- package/dest/class-registry/contract_class_published_event.d.ts.map +1 -1
- package/dest/class-registry/contract_class_published_event.js +9 -13
- package/dest/protocol_contract_data.js +24 -24
- package/dest/scripts/generate_data.js +4 -0
- package/package.json +4 -4
- package/src/class-registry/contract_class_published_event.ts +10 -19
- package/src/protocol_contract_data.ts +24 -24
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"transpiled": true,
|
|
3
|
-
"noir_version": "1.0.0-beta.
|
|
3
|
+
"noir_version": "1.0.0-beta.18+2db78f8894936db05c53430f364360ac9cc5c61f",
|
|
4
4
|
"name": "ContractInstanceRegistry",
|
|
5
5
|
"functions": [
|
|
6
6
|
{
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
|
-
"bytecode": "
|
|
39
|
-
"debug_symbols": "
|
|
38
|
+
"bytecode": "JwACBAEoAAABBIBFJwAABEUlAAAAQScCAQQAJwICBAAfCgABAAIARCUAAABCLQIBRCcCAgREJwIDBAE7DgADAAImJQAAAnUeAgACCScCAwEBJAIAAgAAAF4lAAACmx4CAAIBKQIAAwDvUlNNJwIEAAErAgAFAAAAAAAAAAADAAAAAAAAAAAtCAEGJwIHBAUACAEHAScDBgQBACIGAgctCgcILQ4DCAAiCAIILQ4ECAAiCAIILQ4CCAAiCAIILQ4FCC0LBgIAIgICAi0OAgYtCAECJwIDBAUACAEDAScDAgQBACIGAgMAIgICBD8PAAMABCcCAwQBACoCAwUtCwUEJwICAAAKKgQCAycCAgEACioDAgUkAgAFAAABICUAAAKtHgIAAgYeAgADAC8qAAQAAwAFHAoFBAQcCgQDAAIqBQMELAIAAwAtXgmLgro3tDuZoTFhGP0g1C9RZsnp8T+16mWpbR4KbQQqBAMFHAoFBgQcCgYEAAIqBQQGBCoGAwUcCgUHARwKBwYAHAoGBwECKgUGCCwCAAUAMDPqJG5QbomOl/Vwyv/XBMsLtGAxP7cgsp4TnlwQAAEEKggFCRwKCQoEHAoKCAACKgkICgQqCgMJHAoJCgEcCgoDABwKAwoBAioJAwsEKgsFCRwKCQsEHAoLBQAcCgUJBRYKCgUcCgMKBRwKBQMFBCoKCQUcCggJBRYKBwgcCgYHBRwKCAYFBCoHCQgcCgQJBQwqAgkEKQIAAgUAAVGAJAIABAAAAlwjAAACRAQqBwgDBCoGAgQAKgMEAi0KAgEjAAACdAQqCgUEBCoDAgUAKgQFAi0KAgEjAAACdCYoAAAEBHhFDAAABAMkAAADAAACmioBAAEF2sX11rRKMm08BAIBJioBAAEFT99KitfP8NM8BAIBJioBAAEFursh14IzGGQ8BAIBJg==",
|
|
39
|
+
"debug_symbols": "nVjbbupKDP2XPPMwvszF/MpWVdGWbiEhWrHhSEcV/35siCeANKOz56VZWSEr9njZmeZn+ti+nX+/7g6fX3+m9a+f6e242+93v1/3X++b0+7roOzPFOxPhmlNqymnac2rqcDtINeD8LROetAz0N9AKDMAmgGxA7/Efomdic5EZxI6SDOwKG4gzqAEB/6I4mGIC0q+AQzowASjAggO4gzQGXSGnCFn2MJIBtIMojPRflMUpODAmexMdqaQA00ZUYHFjMaIMhRWE1mopJcIwIExmgWhMbr+ZCt2BUlvp2igzCAbkwwYkxXYQ6kYKDMQZ64PldXEQRnWpzMHBxozg4IYHBij8bBlymTAGA2DLdMbcMbKxNGAMRoPizHZQLyBGIwpBua7YpCZAXbgDBojBuQWfCSaGfPYFbAz5rGoWUTzWMTLZTW5w19Px+3WDH5neW2E781xezhN68N5v19N/2z25+uP/nxvDtfjaXPUqyq5PXzoUQU/d/utoctquTu0bwW1ld+uGLFKRHjQgLaGJEyzhCTOi4I8KGAnilDYg4CwKGQczYNbeXQ1OC4anKilEdsaZIW+KlDioTwYYYmBpRVD7udRJSRWhcIPCqWtgMXXQXux3s/wWFDpWAJqQQURqgTJozOhsxRFbBRdNYokaWt0rEkRayKLrSg8ebtjTYRSZgkESWMaS0FQh21bg9sanMU1uNDSpk816YVBIktZ7+r6HEbPWiDub9BXQsta0JMIUCUC3UnQYI+U9szqOBRFqjUCcCsM7BlU3ytuUBZozr2OP1NdzgzNsddLg0KdvRS4NNOgjkSmuhI55qYE92qKMdWiYm6/A2JPJJhvZpFA3BRJnQVd2jXpPqsp0TEo5trw0hzhvUREMi553BXlOYheXaNtZW5FiZ0wunUt1RoFpVVXgl6TYB1cQncTo+BfaKQ6dbTCgxpRlmaNQxoUIlSNBIMateN1H0yjGlw1MI9pQMxVI6VBjcUeCKNxlLoeugEb08AlF0yDcWCptSUYjWPZ9NzvH/9Kg2LtWko4qFHqOGYY1qjrwTjYL7z0C4/2SyZeXi2Da1rqNKUigz0n2ecHhyBNjf/9pr2r7dM4jb0xpm81H6eB760eL5cXPd28744PHz0uJnbcbd722/n083x4v7t6+vfbr/hHk+/j1/v243zcmtLy5cQ+MfyCICsAfrGPInaq//UDhpeLPf4/"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"name": "public_dispatch",
|
|
@@ -107,8 +107,8 @@
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
|
-
"bytecode": "JwACBAEoAAABBIBUJwAABFQlAAAAQScCAgQBJwIDBAAfCgACAAMAUy0IUwElAAAA8CcCAQRUJwICBAA7DgACAAEpAABDAPqRAsspAABEAMB7XhkpAABFAAVVe/onAEYAAywAAEcALc/
|
|
111
|
-
"debug_symbols": "
|
|
110
|
+
"bytecode": "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",
|
|
111
|
+
"debug_symbols": "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"
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
114
|
"name": "publish_for_public_execution",
|
|
@@ -2095,7 +2095,7 @@
|
|
|
2095
2095
|
}
|
|
2096
2096
|
},
|
|
2097
2097
|
"bytecode": "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",
|
|
2098
|
-
"debug_symbols": "
|
|
2098
|
+
"debug_symbols": "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",
|
|
2099
2099
|
"verification_key": "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"
|
|
2100
2100
|
},
|
|
2101
2101
|
{
|
|
@@ -2152,8 +2152,8 @@
|
|
|
2152
2152
|
}
|
|
2153
2153
|
}
|
|
2154
2154
|
},
|
|
2155
|
-
"bytecode": "JwACBAEoAAABBIBLJwAABEslAAAARicCAgQBJwIDBAAfCgACAAMAShwASkoFLQhKASUAAACMJwIBBEsnAgIEADsOAAIAASgAAEMFAlgsAABEADBkTnLhMaApuFBFtoGBWF0oM+
|
|
2156
|
-
"debug_symbols": "
|
|
2155
|
+
"bytecode": "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",
|
|
2156
|
+
"debug_symbols": "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"
|
|
2157
2157
|
},
|
|
2158
2158
|
{
|
|
2159
2159
|
"name": "update",
|
|
@@ -2216,8 +2216,8 @@
|
|
|
2216
2216
|
}
|
|
2217
2217
|
}
|
|
2218
2218
|
},
|
|
2219
|
-
"bytecode": "JwACBAEoAAABBIBMJwAABEwlAAAAQScCAgQBJwIDBAAfCgACAAMASy0ISwElAAAAqicCAQRMJwICBAA7DgACAAEnAEMAAywAAEQALc/6U80Ocdp7SiJnezNCv8O5BD9Qgb6lg2itAI6qbzcsAABFADBkTnLhMaApuFBFtoGBWF0oM+
|
|
2220
|
-
"debug_symbols": "
|
|
2219
|
+
"bytecode": "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",
|
|
2220
|
+
"debug_symbols": "tZzdblw3DsffZa59IVEUJeVViqJwEqcwYDiBmyywCPLuS1ISOfbiqGOd9ibzM2fmL1Kivngc/7x8fvj4488/Hp+/fP3r8uG3n5ePL49PT49//vH09dP998evz2z9eQnyTyz58iHdXWLlH7O85vHaur3heOWfy90FAo7X8XMs/RVgvNLlQwwMKTKwEmCYgBPagDwteVpoWqgOKDChDKhTudKAJk1UgTyhdUghTSgDIkyYFogT+OvAzidxHqJAGyDOAwnUATlNmBaaFpoWcb4DDRDnO+QB4nwHaaIJtA4ozncoA2KcQANgWtR5BRk69hmTjC0wYJrAjiUeJsxlAMUJNKBMS5mWOi3ic4c2QNNDYShn8bkDN4HcmVk6vAMNgDABJ7QBaVpSHYDydRAoA/K0UJjAjiHHnoukcRTgr2d5q6bxVq3jrUb9LQpxAvXPkHSvfIYi+5ORQTzsIBZONhIPST4juUE8N0gcI3lLHOsgFh5TIrFwb5CMqUCRCURVoA2IYmkCMqc45CKNlijQBqRpkUYL+1wkIQu3XmR0OnAUhV0tLU4QC/tTJdJCAmJhN6pE2mFaJJFKFRAL+1NlFtQgQANQLFFgfiuHYcl5AE2LDEplV6sMijhfC05LG1CnRTKqchRVMqqKq9Jjlf1p+q0m0AbUaWkwgTu8sU4MAYyoD2YMc1iZzAZmA7NJwI2U2NaKkIQ8yGwS9CA0qpNkGRhkNlkIBolKFZKBa01JF80gKGM30az8ryM6VsOYHN0qi/JEFZMoo67MARTVKut7RLWiIhlmt8oAT2yGlByrYXGrLtsddeEOWVGbkK6OPeKiSBMhRMfs2Ax7xB2rIbgVimGPuCpqE9LroBHLXsUo1ii9AxrxQLdKUk9Ex2qoEQ90awVHFZNeB404JkW1ipN9O+qoG9JA/0Bya3IruhWzYzPUTXZgNdRxG+gN62Y70JuowdGbqNqE9GRqybFO1N1rolujW6NbZcWLsvVG3b4GJvksoGIz1DA76mBBViSzyqLLw6BYDItbi1s1JweSYXNrM2vWWTgwOzbDiI5u1ZwcaA3nBI7eBEZHbyJ7w9mbyN6EjqZs/ozVsLi1R6zYI+5Ihs2spD6koCgfkLNEJO3JjtqTcp5gJEPVTUkxG+rRbKBZSwiOV9ZmqFkysBrqejawGKboSIboTejBM0lqFO2djhp8ktzRDXOiWXXT5NmhSIY6mnLAYayGya29+zrq12Td0X2SZ4didmyGuqx07P3bUcKUY1CsupYMdKu6jlGR5tdaCI7WWotujehoPrQeW0dtQga2aSKiXgI0ioGigKjYDMmtGsXAYljdqqkxUJuQo3xQ1wdeWbUJElTXxQfGaqiuD3SrTrKBxVBHqGMPSC80Oiwol4egE2dgMdQEH0iGGkUOiujYJvYNe6Bbo1ujW0F9aIJJPxAV9S4EgnKSH5j1YpQU9SKEghQdRUyOrHxJC45urW6t1VAX84FmBZ0BHaM2QYpkCG7VKLLeBlOY7kAPqGMzRLdiNczJUa99Va+W4KgNS0dBiY5urejYDJtZUwBHaYL6pRUc3aqxyZkf+n6sPqQeW8dsiG7tsXVshhobgWI11NjkNgF9P+5Y3KqDNTAbNrfqYCn2nZdQsRpGt/bY9C6ua6r6gBpbR11TB7pVYxuYHZuhx4YeW9+P5fIDesscqOM20K3VrdWtza1NXZc8y7pAd2zaRFWkidQ/0FH8lcsVkC6DA6+szVAPIwPdmtya3Ipu1UztqLNwoDehiSgXISiacnKP4/QFs+p0krscVz1UARXJMLm1+6DYfejo1u6Oog5A0SKKJlfH4lYdALkggl4no1ztoO+QciWEvkPKpRD6Dim3Qeg7pEbRd8iOvX/h16+7yyw4/fH95eFB6k1XFSiuS327f3l4/n758Pzj6enu8p/7px/6ob++3T/r6/f7F36Xm3p4/syvLPjl8elB6Nedfzscf7UWuUrqtyv7ZQI5vlKIxwp8BMKhwPf84grtlQIcKyRZz1UgEdr3tX9u9ECus92DjHjkAa48yEMAeZ9xgb1ebEe9SMcKRdYlFeBUs+8j3OpB05OcCjTe8448qItejFJL6L3IR4SjXmzHClCmAG8jR+O4iiFIVWTEEOEwFxepwPvezCXec+JREHGRjbmFmQzElQ+T4J3ktUZajQZ6JCUcayxykoKNKHFlxTXe4UWdM7Px6ePYi0VeVv7mzOxG7VijLGZXnhKp+fqQwjuGFeMcE943D2d4XCQnj8jsDD4x57PpmekoPVcKWOdS3XKMRwoApxMc0vkEBzyf4FJ5OJfgay9uS3Ao5xMc6tkEXw7rbQmewr+a4FfpyYe5nQQvcq3vCnwiOlJIi+zkCtXsCa62eBgVX0ss0gIsDD7y+14a3/RlPp/eic6m99qL29I71fPpndrZ9F4Oamxz1eK6GR0NKi62AC7NmwQ/fHCJtJOcFQ/Xb1zFQXZMkxrekRO4PGq2mVqJn/cdSuRVV0Am6ws4PnMjrURCLCYS0vGxuZw+M2I9eWhcBcJPtsDjwHrkRA6rDMdkg7LrRgvuRsyHfYFLN7K7UY5yIy8yFLTC3/uTC6A+Wyu8RyO5Rj3UWM6UEi1FS6qHoSx6NJVk6w7f1Q8lyj8wU3L9B2ZKbqdnCoWTM2UVyK0zheD0TFmPq12WOaPa0bjSaodvYMello4zdK1BdkzgEd7UyFa6uJ7z79FIIduGEChuahRbOPi56a4GmgaUPQ0tag8Nok0NTw8uxu9qWH9w9XpPAzwWoE0/wK6MfFnb9cOPswlwTyNlm7VcSN/UqLYcY9zWsP5A2Jwv6PMFd+dLSehby2afVltN+Un/5pxrZa4fyE/wNndam/tcfz7cJuvCjYomUbEdFhXq6jJvB/xyNWfLO8KoYOf7elXAfBvGYrfnh6B2bgl4PWPzzW7Ig1TXgMPj+VLC7kv8HDQcSbRVPTnb6Yn74nqelNcaqwtTtfOCPM0+1FiGAuYHP7Q8vKy0hQQ/akOrrYfDg2BblXls4WnNR+TNBbYtkjMHe0SR42KrX2pE2+p5cMqmhh0kMx+Q9zSuYymwpwF2fMpcRdyMxQ60rFFOxwKLY9w6luyxNNrTSGFusYzbflgsKcLp/khxc1wSWX/wNrepYWsxa9TzsZS26Uebyw9fOzbHFtHGFrHu+mF9ijmd7g9cHDlWCyEXvvwCd6Xx9lnM6rHSzQ90Yj7/RIdWRQZbPyBez9t3iXixGKCmhcjiWozFRhdr8pn7pl68dCR59YexHjqy3CmjVTi5lH9YXIywrJKW5rWKV4+i3z4BhZVKJk80Ll0cqyziSeQXyhIPH0j8nSd2Y2BPrkrHbzwJyyJQ9Gjg6jj19sEyrOqlAFbfg5yPe4RuK4NDXvTqqhpF/piHcOcxj/zyox8M82GuriSqB9KuSjjvkWhemWu57EkUyw0+I+5IQKBoZ/WCWxLoNwaEPS8wuQSFLYkcLJAMtCeRg0nkuCeB6BKw6YVdOXKpp73YlbAEl19825IgtGsg5b1BJStRcgVq0ws7lgLVcDqQPQm+c1r9qVbclPAzR9ga1NSSVY5eHX3enhawnT4tLN2wUy1j2YvktuPGalSj7QLw6k78nsWz+bOmsDfbo23NvEmHzUDIJc4HsikRfQmPWPYkrODMZZe2KWG7wKvfW9gMZFfitqP9SgJ8UCHWTYngEu1sILsSt95QiP7NNacE+1USRj/zcdfeqqD/H29UeK99qG/iWP0OHtjGzOdk2PLC5ghj21Joc0zLrg92rynxaj98hwLYYY2x7EXRXKGeVYhbPoBVEsr1Q7bNsbj6Zcb3+JCyKeS9KKw+/X/58Dv/dP/p8eXVn4X4JVovj/cfnx7Gj19+PH+6evf7f7/Nd+aflfj28vXTw+cfLw+i5H9bgv/5Tc6qmdLvd5coP1G5yxXlJ3kTuH9S0DflXV4H7rDG33+Ja/8D"
|
|
2221
2221
|
}
|
|
2222
2222
|
],
|
|
2223
2223
|
"outputs": {
|
|
@@ -2885,21 +2885,25 @@
|
|
|
2885
2885
|
"path": "std/panic.nr",
|
|
2886
2886
|
"source": "pub fn panic<T, U>(message: T) -> U\nwhere\n T: StringLike,\n{\n assert(false, message);\n crate::mem::zeroed()\n}\n\ntrait StringLike {}\n\nimpl<let N: u32> StringLike for str<N> {}\nimpl<let N: u32, T> StringLike for fmtstr<N, T> {}\n"
|
|
2887
2887
|
},
|
|
2888
|
-
"
|
|
2888
|
+
"441": {
|
|
2889
2889
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr",
|
|
2890
2890
|
"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 mut 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"
|
|
2891
2891
|
},
|
|
2892
|
-
"
|
|
2892
|
+
"447": {
|
|
2893
|
+
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr",
|
|
2894
|
+
"source": "pub(crate) mod assert_trailing_zeros;\npub(crate) mod splice_at_count;\npub(crate) mod find_index;\npub(crate) mod get_sorted_tuples;\npub(crate) mod claimed_length_array;\n\n// Re-exports.\npub use assert_trailing_zeros::assert_trailing_zeros;\npub use claimed_length_array::ClaimedLengthArray;\npub use find_index::{find_first_index, find_last_index};\npub use get_sorted_tuples::{get_sorted_tuples, SortedTuple};\npub use splice_at_count::splice_at_count;\n\nuse crate::traits::Empty;\n\n// TODO: Consider making this a part of the noir stdlib.\n/// Helper fn to create a subarray from a given array.\npub fn subarray<T, let N: u32, let M: u32>(array: [T; N], offset: u32) -> [T; M]\nwhere\n T: Empty,\n{\n let mut result: [T; M] = [T::empty(); M];\n for i in 0..M {\n result[i] = array[offset + i];\n }\n result\n}\n\n/// Helper function to count the number of non-empty elements in a validated array.\n/// Danger: This is only safe to call if the input arrays have been \"validated\" (dense lhs, empty rhs).\n/// 1. All elements before the first empty element are non-empty\n/// 2. All elements after and including the first empty element are empty\n/// 3. The array forms a contiguous sequence of non-empty elements followed by empty elements\npub fn array_length<T, let N: u32>(array: [T; N]) -> u32\nwhere\n T: Empty,\n{\n // We get the length by checking the index of the first empty element.\n\n // Safety: This is safe because we have validated the array (see function doc comment above) and the emptiness\n // of the element and non-emptiness of the previous element is checked below.\n let length = unsafe { find_first_index(array, |elem: T| elem.is_empty()) };\n\n validate_array_length_hint(array, length);\n\n length\n}\n\n// Extracted into a standalone function to enable testing of bad hints.\nfn validate_array_length_hint<T, let N: u32>(array: [T; N], length: u32)\nwhere\n T: Empty,\n{\n // Note: if length > N, the below `array` access will throw an out of bounds error.\n\n if length != N {\n array[length].assert_empty(\"Expected array[length] to be empty\");\n }\n\n if length != 0 {\n assert(\n !array[length - 1].is_empty(),\n \"Expected claimed final element of array (array[length - 1]) to be nonempty\",\n );\n }\n}\n\n// Returns an array length defined by fully trimming _all_ \"empty\" items\n// from the RHS.\npub unconstrained fn trimmed_array_length_hint<T, let N: u32>(array: [T; N]) -> u32\nwhere\n T: Empty,\n{\n let index_of_last_nonempty = find_last_index(array, |elem: T| !elem.is_empty());\n let length: u32 = if index_of_last_nonempty != N {\n 1 + index_of_last_nonempty\n } else {\n 0\n };\n length\n}\n\n// Returns the number of consecutive elements at the start of the array for which the predicate returns false.\n// This function ensures that any element after the first matching element (predicate returns true) also matches the predicate.\npub fn array_length_until<T, let N: u32, Env>(array: [T; N], predicate: fn[Env](T) -> bool) -> u32 {\n let mut length = 0;\n let mut stop = false;\n for i in 0..N {\n if predicate(array[i]) {\n stop = true;\n } else {\n assert(\n stop == false,\n \"matching element found after already encountering a non-matching element\",\n );\n length += 1;\n }\n }\n length\n}\n\npub fn check_permutation<T, let N: u32>(\n original_array: [T; N],\n permuted_array: [T; N],\n original_indexes: [u32; N],\n)\nwhere\n T: Eq,\n{\n let mut seen_value = [false; N];\n for i in 0..N {\n let index = original_indexes[i];\n let original_value = original_array[index];\n assert(permuted_array[i].eq(original_value), \"Invalid index\");\n assert(!seen_value[index], \"Duplicated index\");\n seen_value[index] = true;\n }\n}\n\n// Helper function to check if an array is padded with a given value from a given index.\npub fn array_padded_with<T, let N: u32>(array: [T; N], from_index: u32, padded_with: T) -> bool\nwhere\n T: Eq,\n{\n let mut is_valid = true;\n let mut should_check = false;\n for i in 0..N {\n should_check |= i == from_index;\n is_valid &= !should_check | (array[i] == padded_with);\n }\n is_valid\n}\n\n// ==================== subarray tests ====================\n\n#[test]\nfn test_subarray() {\n assert_eq(subarray::<_, 5, 3>([10, 20, 30, 40, 50], 1), [20, 30, 40]);\n assert_eq(subarray::<_, 5, 2>([10, 20, 30, 40, 50], 0), [10, 20]);\n assert_eq(subarray::<_, 3, 0>([10, 20, 30], 2), []);\n assert_eq(subarray::<_, 3, 1>([10, 20, 30], 2), [30]);\n}\n\n#[test(should_fail_with = \"out of bounds\")]\nfn test_subarray_offset_out_of_bounds() {\n let _: [Field; 1] = subarray([10, 20, 30], 5);\n}\n\n#[test(should_fail_with = \"out of bounds\")]\nfn test_subarray_result_size_exceeds_available() {\n let _: [Field; 3] = subarray([10, 20, 30, 40, 50], 3);\n}\n\n// ==================== array_length tests ====================\n\n#[test]\nfn test_array_length_empty_array() {\n assert_eq(array_length([0]), 0);\n assert_eq(array_length([0, 0, 0]), 0);\n}\n\n#[test]\nfn test_array_length() {\n assert_eq(array_length([123]), 1);\n assert_eq(array_length([123, 0, 0]), 1);\n assert_eq(array_length([123, 456]), 2);\n assert_eq(array_length([123, 456, 0]), 2);\n}\n\n#[test]\nfn test_array_length_invalid_arrays() {\n // Result can be misleading (but correct) for invalid arrays.\n // This is why the arrays being passed-into `array_length` must already have been \"validated\"\n // (dense lhs, empty rhs).\n assert_eq(array_length([0, 0, 123]), 0);\n assert_eq(array_length([0, 123, 0]), 0);\n assert_eq(array_length([0, 123, 456]), 0);\n assert_eq(array_length([123, 0, 456]), 1);\n}\n\n// ==================== validate_array_length_hint tests ====================\n\n#[test]\nfn test_validate_array_length_hint_valid() {\n validate_array_length_hint([0, 0, 0], 0);\n validate_array_length_hint([10, 20, 0], 2);\n validate_array_length_hint([10, 20, 30], 3);\n}\n\n#[test(should_fail_with = \"Expected array[length] to be empty\")]\nfn test_validate_array_length_hint_claims_zero_when_not_empty() {\n // Invalid: hint says length 0, but first element is not empty\n validate_array_length_hint([10, 20, 30], 0);\n}\n\n#[test(should_fail_with = \"Expected array[length] to be empty\")]\nfn test_validate_array_length_hint_too_short() {\n // Invalid: hint says length 1, but element at index 1 is not empty\n validate_array_length_hint([10, 20, 0], 1);\n}\n\n#[test(should_fail_with = \"Expected claimed final element of array (array[length - 1]) to be nonempty\")]\nfn test_validate_array_length_hint_too_long() {\n // Invalid: hint says length 2, but element at index 1 is empty\n validate_array_length_hint([10, 0, 0], 2);\n}\n\n#[test(should_fail_with = \"Expected claimed final element of array (array[length - 1]) to be nonempty\")]\nfn test_validate_array_length_hint_of_empty_too_long() {\n // Invalid: hint says length 2, but element at index 1 is empty\n validate_array_length_hint([0, 0, 0], 2);\n}\n\n#[test(should_fail_with = \"out of bounds\")]\nfn test_validate_array_length_hint_out_of_bounds() {\n // Invalid: hint says length 4, but array only has 3 elements\n validate_array_length_hint([10, 20, 30], 4);\n}\n\n// ==================== trimmed_array_length_hint tests ====================\n\n#[test]\nunconstrained fn test_trimmed_array_length_hint_with_trailing_empties() {\n assert_eq(trimmed_array_length_hint([10, 20, 30, 0, 0]), 3);\n}\n\n#[test]\nunconstrained fn test_trimmed_array_length_hint_fully_empty() {\n assert_eq(trimmed_array_length_hint([0, 0, 0, 0, 0]), 0);\n}\n\n#[test]\nunconstrained fn test_trimmed_array_length_hint_no_empties() {\n assert_eq(trimmed_array_length_hint([10, 20, 30, 40, 50]), 5);\n}\n\n#[test]\nunconstrained fn test_trimmed_array_length_hint_with_gaps() {\n // Unlike array_length, this trims from the right only, so gaps don't matter\n assert_eq(trimmed_array_length_hint([10, 0, 30, 0, 0]), 3);\n}\n\n// ==================== array_length_until tests ====================\n\n#[test]\nfn test_array_length_until() {\n let array = [11, 22, 33, 44, 55];\n assert_eq(array_length_until(array, |x| x == 55), 4);\n assert_eq(array_length_until(array, |x| x == 56), 5);\n assert_eq(array_length_until(array, |x| x > 40), 3);\n assert_eq(array_length_until(array, |x| x > 10), 0);\n}\n\n#[test(should_fail_with = \"matching element found after already encountering a non-matching element\")]\nfn test_array_length_until_non_consecutive_fails() {\n let array = [1, 1, 0, 1, 0];\n let _ = array_length_until(array, |x| x == 0);\n}\n\n#[test(should_fail_with = \"matching element found after already encountering a non-matching element\")]\nfn test_array_length_until_first_non_matching_fails() {\n let array = [1, 0, 0, 0, 0];\n let _ = array_length_until(array, |x| x == 1);\n}\n\n// ==================== check_permutation tests ====================\n\n#[test]\nfn test_check_permutation() {\n let original_array = [1, 2, 3];\n let permuted_array = [3, 1, 2];\n let indexes = [2, 0, 1];\n check_permutation(original_array, permuted_array, indexes);\n}\n\n#[test(should_fail_with = \"Duplicated index\")]\nfn test_check_permutation_duplicated_index() {\n let original_array = [0, 1, 0];\n let permuted_array = [1, 0, 0];\n let indexes = [1, 0, 0];\n check_permutation(original_array, permuted_array, indexes);\n}\n\n#[test(should_fail_with = \"Invalid index\")]\nfn test_check_permutation_invalid_index() {\n let original_array = [0, 1, 2];\n let permuted_array = [1, 0, 0];\n let indexes = [1, 0, 2];\n check_permutation(original_array, permuted_array, indexes);\n}\n\n// ==================== array_padded_with tests ====================\n\n#[test]\nfn test_array_padded_with() {\n let array = [11, 22, 33, 44, 44];\n assert_eq(array_padded_with(array, 0, 44), false);\n assert_eq(array_padded_with(array, 1, 44), false);\n assert_eq(array_padded_with(array, 2, 44), false);\n assert_eq(array_padded_with(array, 3, 44), true);\n assert_eq(array_padded_with(array, 4, 44), true);\n assert_eq(array_padded_with(array, 4, 33), false);\n assert_eq(array_padded_with(array, 5, 44), true); // Index out of bounds.\n assert_eq(array_padded_with(array, 0, 11), false);\n}\n"
|
|
2895
|
+
},
|
|
2896
|
+
"454": {
|
|
2893
2897
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/reader.nr",
|
|
2894
2898
|
"source": "pub struct Reader<let N: u32> {\n data: [Field; N],\n offset: u32,\n}\n\nimpl<let N: u32> Reader<N> {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array<let K: u32>(&mut self) -> [Field; K] {\n let mut result = [0; K];\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n pub fn read_struct<T, let K: u32>(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array<T, let K: u32, let C: u32>(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn peek_offset(&mut self, offset: u32) -> Field {\n self.data[self.offset + offset]\n }\n\n pub fn advance_offset(&mut self, offset: u32) {\n self.offset += offset;\n }\n\n pub fn finish(self) {\n assert_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n"
|
|
2895
2899
|
},
|
|
2896
|
-
"
|
|
2900
|
+
"455": {
|
|
2897
2901
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/serialization.nr",
|
|
2898
2902
|
"source": "use crate::{reader::Reader, writer::Writer};\n\n// docs:start:serialize\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\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/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\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/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n\n // We care only about the name and type so we drop the last item of the tuple\n let params = nested_struct.0.fields(nested_struct.1).map(|(name, typ, _)| (name, typ));\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote {Serialize});\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = params\n .map(|(name, _typ): (Quoted, Type)| {\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {});\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n// docs:start:deserialize\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<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/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\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 x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote {Deserialize});\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote {0}\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_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 $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - An array of tuples where each tuple contains a quoted parameter name and its Type. The type needs\n/// to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [(Quoted, Type)]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote {$name}\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
|
|
2899
2903
|
},
|
|
2900
|
-
"
|
|
2904
|
+
"457": {
|
|
2901
2905
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/type_impls.nr",
|
|
2902
|
-
"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"
|
|
2906
|
+
"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"
|
|
2903
2907
|
},
|
|
2904
2908
|
"5": {
|
|
2905
2909
|
"path": "std/cmp.nr",
|
|
@@ -2907,7 +2911,7 @@
|
|
|
2907
2911
|
},
|
|
2908
2912
|
"51": {
|
|
2909
2913
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/contract_instance_registry_contract/src/main.nr",
|
|
2910
|
-
"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 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"
|
|
2914
|
+
"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 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_return_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"
|
|
2911
2915
|
},
|
|
2912
2916
|
"58": {
|
|
2913
2917
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/context/private_context.nr",
|
|
@@ -2935,7 +2939,7 @@
|
|
|
2935
2939
|
},
|
|
2936
2940
|
"83": {
|
|
2937
2941
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/state_vars/delayed_public_mutable.nr",
|
|
2938
|
-
"source": "use crate::protocol::{\n delayed_public_mutable::{\n delayed_public_mutable_values::{unpack_delay_change, unpack_value_change},\n DelayedPublicMutableValues,\n ScheduledDelayChange,\n ScheduledValueChange,\n },\n traits::Packable,\n};\n\nuse crate::{context::{PrivateContext, PublicContext, UtilityContext}, state_vars::StateVariable, utils::WithHash};\n\n/// Mutable public values with private read access.\n///\n/// This is an advanced public state variable, with no native Solidity equivalent.\n///\n/// Like [`PublicMutable`](crate::state_vars::PublicMutable) it represents a public value of type `T` that can be\n/// written to repeatedly, but with a key improvement: the current value can also be **read from a private contract\n/// function**.\n///\n/// This comes at the cost of extra restrictions on the state variable: writes do not come into effect immediately,\n/// they must be **scheduled** to take place after some minimum delay. Reading from the state variable will therefore\n/// return the previous value until some time passes, which is why this is a _delayed_ mutable variable.\n///\n/// It is these delays that enable the capacity for reads from private contract functions, as they provide guarantees\n/// regarding how long can some historical state observed at the anchor block be known to not change.\n///\n/// Delays can be modified during the lifetime of the contract.\n///\n/// ## Access Patterns\n///\n/// The current value stored in a `DelayedPublicMutable` can be read from public contract functions, and writes can be\n/// scheduled to happen in the future.\n///\n/// Public contract functions can also schedule changes to the write delay, as well as inspect any already scheduled\n/// value or delay changes.\n///\n/// Private contract functions can read the **current** value of the state variable, but not past or scheduled values.\n/// They cannot read the current delay, and they cannot schedule any kind of value change.\n///\n/// ## Privacy\n///\n/// The value stored in `DelayedPublicMutable` is fully public, as are all scheduled value and delay changes.\n///\n/// Reads from a private contract function are almost fully private: the only observable effect is that they set the\n/// transaction's `expiration_timestamp` property, possibly reducing the privacy set. See\n/// [`PrivateContext::set_expiration_timestamp`](crate::context::PrivateContext::set_expiration_timestamp).\n///\n/// ## Use Cases\n///\n/// These are mostly an extension of [`PublicMutable`](crate::state_vars::PublicMutable)'s, given that what this state\n/// variable essentially achieves is to provide private reads to it. For example, it can be used for global contract\n/// configuration (such as fees, access control, etc.) that users will need to access during private interactions.\n///\n/// The key consideration is whether the enforced minimum delay on writes prevents using this state variable. In some\n/// scenarios this restriction is incompatible with requirements (such as a token's total supply, which must always be\n/// up to date), while in others the enhanced privacy might make the tradeoff acceptable (such as when dealing with\n/// contract pauses or access control revocation, where a delay of some hours could be acceptable).\n///\n/// Note that, just like in [`PublicMutable`](crate::state_vars::PublicMutable), the fact that the values are public\n/// does not necessarily mean the actions that update these values must themselves be wholly public. To learn more,\n/// see the notes there regarding usage of [`only_self`](crate::macros::functions::only_self).\n///\n/// ## Choosing Delays\n///\n/// A short delay reduces the most obvious downside of `DelayedPublicMutable`, and so it is natural to wish to make it\n/// be as low as possible. It is therefore important to understand the tradeoffs involved in delay selection.\n///\n/// A shorter delay will result in a lower `expiration_timestamp` property of transactions that privately read the\n/// state variable, reducing its privacy set. If the delay is smaller than that of any other contract, then this\n/// privacy leak might be large enough to uniquely identify those transactions that interact with the contract - fully\n/// defeating the purpose of `DelayedPublicMutable`.\n///\n/// Additionally, a lower `expiration_timestamp` obviously causes transactions to expire earlier, resulting in\n/// multiple issues. Among others, this can make large transactions that take long to prove be unfeasible, restrict\n/// users with slow proving devices, and force large transaction fees to guarantee fast inclusion.\n///\n/// In practice, a delay of at least a couple hours is recommended. From a privacy point of view the optimal delay is\n/// [`crate::protocol::constants::MAX_TX_LIFETIME`], which puts contracts in the same privacy set as those that do not\n/// use `DelayedPublicMutable` at all.\n///\n/// ## Examples\n///\n/// Declaring a `DelayedPublicMutable` in the contract's [`storage`](crate::macros::storage::storage) struct\n/// requires specifying the type `T` that is stored in the variable, along with the initial delay used when scheduling\n/// value changes:\n///\n/// ```noir\n/// global PAUSE_CONTRACT_INITIAL_DELAY_S: u64 = 6 * 60 * 60; // 6 hours\n/// global CHANGE_AUTHORIZATION_INITIAL_DELAY_S: u64 = 24 * 60 * 60; // 24 hours\n///\n/// #[storage]\n/// struct Storage<C> {\n/// paused: DelayedPublicMutable<bool, PAUSE_CONTRACT_INITIAL_DELAY_S, C>,\n/// user_authorization: Map<AztecAddress, DelayedPublicMutable<bool, CHANGE_AUTHORIZATION_INITIAL_DELAY_S, C>, C>,\n/// }\n/// ```\n///\n/// Note that this initial delay can be altered during the contract's lifetime via\n/// [`DelayedPublicMutable::schedule_delay_change`].\n///\n/// ## Requirements\n///\n/// The type `T` stored in the `DelayedPublicMutable` must implement the `Eq` and\n/// [`Packable`](crate::protocol::traits::Packable) traits.\n///\n/// ## Implementation Details\n///\n/// This state variable stores more information in public storage than\n/// [`PublicMutable`](crate::state_vars::PublicMutable), as it needs to keep track of the current and scheduled change\n/// information for both the value and the delay - see\n/// [`crate::protocol::delayed_public_mutable::DelayedPublicMutableValues`].\n///\n/// It also stores a hash of this entire configuration so that private reads can be performed in a single historical\n/// public storage read - see [`crate::utils::WithHash`].\n///\n/// This results in a total of `N * 2 + 2` storage slots used, where `N` is the packing length of the stored type `T`.\n/// This makes it quite important to ensure `T`'s implementation of [`Packable`](crate::protocol::traits::Packable) is\n/// space-efficient.\npub struct DelayedPublicMutable<T, let InitialDelay: u64, Context> {\n context: Context,\n storage_slot: Field,\n}\n\n// We allocate `M + 1` slots because we're going to store a `WithHash<DelayedPublicMutableValues<T, InitialDelay>>`,\n// and `WithHash` increases the packing length by one.\nimpl<T, let InitialDelay: u64, Context, let M: u32> StateVariable<M + 1, Context> for DelayedPublicMutable<T, InitialDelay, Context>\nwhere\n DelayedPublicMutableValues<T, InitialDelay>: Packable<N = M>,\n{\n fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, PublicContext>\nwhere\n T: Eq,\n{\n /// Schedules a write to the current value.\n ///\n /// The current value does not immediately change. Once the current delay passes,\n /// [`get_current_value`](DelayedPublicMutable::get_current_value) automatically begins to return `new_value`.\n ///\n /// ## Multiple Scheduled Changes\n ///\n /// Only a **single** value can be scheduled to become the new value at a given point in time. Any prior scheduled\n /// changes which have not yet become current are **replaced** with the new one and discarded.\n ///\n /// To illustrate this, consider a scenario at `t0` with a current value `A`. A value change to `B` is scheduled to\n /// occur at `t1`. At some point _before_ `t1`, a second value change to `C` is scheduled to occur at `t2` (`t2 >\n /// t1`). The result is that the current value continues to be `A` all the way until `t2`, at which point it\n /// changes to `C`.\n ///\n /// This also means that it is possible to **cancel** a scheduled change by calling `schedule_value_change` with\n /// the current value.\n ///\n /// ## Examples\n ///\n /// A public setter that authorizes a user:\n /// ```noir\n /// #[external(\"public\")]\n /// fn authorize_user(user: AztecAddress) {\n /// assert_eq(self.storage.admin.read(), self.msg_sender(), \"caller is not admin\");\n /// self.storage.user_authorization.at(user).schedule_value_change(true);\n /// }\n /// ```\n ///\n /// ## Cost\n ///\n /// The `SSTORE` AVM opcode is invoked `2 * N + 2` times, where `N` is `T`'s packed length.\n pub fn schedule_value_change(self, new_value: T)\n where\n T: Packable,\n {\n let _ = self.schedule_and_get_value_change(new_value);\n }\n\n /// Schedules a write to the current value, returning the scheduled entry.\n pub fn schedule_and_get_value_change(self, new_value: T) -> ScheduledValueChange<T>\n where\n T: Packable,\n {\n let mut value_change = self.read_value_change();\n let delay_change = self.read_delay_change();\n\n let current_timestamp = self.context.timestamp();\n let current_delay = delay_change.get_current(current_timestamp);\n\n // TODO: make this configurable https://github.com/AztecProtocol/aztec-packages/issues/5501\n let timestamp_of_change = current_timestamp + current_delay;\n value_change.schedule_change(new_value, current_timestamp, current_delay, timestamp_of_change);\n\n self.write(value_change, delay_change);\n\n value_change\n }\n\n /// Schedules a write to the current delay.\n ///\n /// This works just like [`schedule_value_change`](DelayedPublicMutable::schedule_value_change), except instead of\n /// changing the value in the state variable, it changes the delay that will govern future invocations of that\n /// function.\n ///\n /// The current delay does not immediately change. Once the current delay passes,\n /// [`get_current_delay`](DelayedPublicMutable::get_current_delay) automatically begins to return `new_delay`, and\n /// [`schedule_value_change`](DelayedPublicMutable::schedule_value_change) begins using it.\n ///\n /// ## Multiple Scheduled Changes\n ///\n /// Only a **single** delay can be scheduled to become the new delay at a given point in time. Any prior scheduled\n /// changes which have not yet become current are **replaced** with the new one and discarded.\n ///\n /// To illustrate this, consider a scenario at `t0` with a current delay `A`. A delay change to `B` is scheduled to\n /// occur at `t1`. At some point _before_ `t1`, a second delay change to `C` is scheduled to occur at `t2` (`t2 >\n /// t1`). The result is that the current delay continues to be `A` all the way until `t2`, at which point it\n /// changes to `C`.\n ///\n /// ## Delays When Changing Delays\n ///\n /// A delay change cannot always be immediate: if it were, then it'd be possible to break `DelayedPublicMutable`'s\n /// invariants by setting the delay to a very low or zero value and then scheduling a value change, resulting in a\n /// new value becoming the current one earlier than was predictable based on the prior delay. This would prohibit\n /// private reads, which is the reason for existence of this state variable.\n ///\n /// Instead, delay changes are themselves scheduled and delay so that the property mentioned above is preserved.\n /// This results in delay increases and decreases being asymmetrical.\n ///\n /// If the delay is being decreased, then this requires a delay equal to the difference between the current and new\n /// delay, so that a scheduled value change that occurred as the new delay came into effect would be scheduled for\n /// the same timestamp as if no delay change had occurred.\n ///\n /// If the delay is being increased, then the new delay becomes effective immediately, as new value changes would\n /// be scheduled for a timestamp that is further than the current delay.\n ///\n /// ## Examples\n ///\n /// A public setter that sets the pause delay:\n /// ```noir\n /// #[public]\n /// fn set_pause_delay(delay: u64) {\n /// assert_eq(self.storage.admin.read(), self.msg_sender(), \"caller is not admin\");\n /// self.storage.paused.schedule_delay_change(delay);\n /// }\n /// ```\n ///\n /// ## Cost\n ///\n /// The `SSTORE` AVM opcode is invoked `2 * N + 2` times, where `N` is `T`'s packed length.\n pub fn schedule_delay_change(self, new_delay: u64)\n where\n T: Packable,\n {\n let mut delay_change = self.read_delay_change();\n\n let current_timestamp = self.context.timestamp();\n\n delay_change.schedule_change(new_delay, current_timestamp);\n\n // We can't just update the `ScheduledDelayChange`, we need to update the entire storage because we need to\n // also recompute and write the hash.\n // We _could_ just read everything, update the hash and `ScheduledDelayChange` but not overwrite the\n // `ScheduledValueChange`, resulting in fewer storage writes, but that would require careful handling of\n // storage slots and `WithHash`'s internal layout, which is not worth doing at this point.\n self.write(self.read_value_change(), delay_change);\n }\n\n /// Returns the current value.\n ///\n /// If [`schedule_value_change`](DelayedPublicMutable::schedule_value_change) has never been called, then this\n /// returns the default empty public storage value, which is all zeroes - equivalent to `let t =\n /// T::unpack(std::mem::zeroed());`.\n ///\n /// It is not possible to detect if a `DelayedPublicMutable` has ever been initialized or not other than by testing\n /// for the zero sentinel value. For a more robust solution, store an `Option<T>` in the `DelayedPublicMutable`.\n ///\n /// Use [`get_scheduled_value`](DelayedPublicMutable::get_scheduled_value) to instead get the last value that was\n /// scheduled to become the current one (which will equal the current value if the delay has already passed).\n ///\n /// ## Examples\n ///\n /// A public getter that returns a user's authorization status:\n /// ```noir\n /// #[external(\"public\")]\n /// fn is_authorized(user: AztecAddress) -> bool {\n /// self.storage.user_authorization.at(user).get_current_value()\n /// }\n /// ```\n ///\n /// ## Cost\n ///\n /// The `SLOAD` AVM opcode is invoked `2 * N + 1` times, where `N` is `T`'s packed length.\n pub fn get_current_value(self) -> T\n where\n T: Packable,\n {\n let current_timestamp = self.context.timestamp();\n let value_change = self.read_value_change();\n\n value_change.get_current_at(current_timestamp)\n }\n\n /// Returns the current delay.\n ///\n /// This is the delay that would be used by [`schedule_value_change`](DelayedPublicMutable::schedule_value_change)\n /// if it were called in the current transaction.\n ///\n /// If [`schedule_delay_change`](DelayedPublicMutable::schedule_delay_change) has never been called, then this\n /// returns the `InitialDelay` used in the [`storage`](crate::macros::storage::storage) struct.\n ///\n /// Use [`get_scheduled_delay`](DelayedPublicMutable::get_scheduled_delay) to instead get the last delay that was\n /// scheduled to become the current one (which will equal the current delay if the delay has already passed).\n ///\n /// ## Examples\n ///\n /// A public getter that returns the pause delay:\n /// ```noir\n /// #[external(\"public\")]\n /// fn get_pause_delay() -> u64 {\n /// self.storage.paused.get_current_delay()\n /// }\n /// ```\n ///\n /// ## Cost\n ///\n /// The `SLOAD` AVM opcode is invoked a single time, regardless of `T`.\n pub fn get_current_delay(self) -> u64\n where\n T: Packable,\n {\n let current_timestamp = self.context.timestamp();\n self.read_delay_change().get_current(current_timestamp)\n }\n\n /// Returns the last scheduled value and timestamp of change.\n pub fn get_scheduled_value(self) -> (T, u64)\n where\n T: Packable,\n {\n self.read_value_change().get_scheduled()\n }\n\n /// Returns the last scheduled delay and timestamp of change.\n pub fn get_scheduled_delay(self) -> (u64, u64)\n where\n T: Packable,\n {\n self.read_delay_change().get_scheduled()\n }\n\n fn read_value_change(self) -> ScheduledValueChange<T>\n where\n T: Packable,\n {\n // We don't read ScheduledValueChange directly by having it implement Packable because ScheduledValueChange and\n // ScheduledDelayChange are packed together (sdc and svc.timestamp_of_change are stored in the same slot).\n let packed = self.context.storage_read(self.storage_slot);\n unpack_value_change::<T, <T as Packable>::N>(packed)\n }\n\n fn read_delay_change(self) -> ScheduledDelayChange<InitialDelay>\n where\n T: Packable,\n {\n // Since all ScheduledDelayChange member are packed into a single field, we can read a single storage slot here\n // and skip the ones that correspond to ScheduledValueChange members. We are abusing the fact that the field\n // containing the ScheduledDelayChange data is the first one in the storage layout - otherwise we'd need to\n // offset the storage slot to get the position where it'd land. We don't read ScheduledDelayChange directly by\n // having it implement Packable because ScheduledValueChange and ScheduledDelayChange are packed together (sdc\n // and svc.timestamp_of_change are stored in the same slot).\n let packed = self.context.storage_read(self.storage_slot);\n unpack_delay_change::<InitialDelay>(packed)\n }\n\n fn write(self, value_change: ScheduledValueChange<T>, delay_change: ScheduledDelayChange<InitialDelay>)\n where\n T: Packable,\n {\n // Whenever we write to public storage, we write both the value change and delay change to storage at once. We\n // do so by wrapping them in a single struct (`DelayedPublicMutableValues`). Then we wrap the resulting struct\n // in `WithHash`. Wrapping in `WithHash` makes for more costly writes but it also makes private proofs much\n // simpler because they only need to produce a historical proof for the hash, which results in a single\n // inclusion proof (as opposed to 4 in the best case scenario in which T is a single field). Private delayed\n // public mutable reads are assumed to be much more frequent than public writes, so this tradeoff makes sense.\n let values = WithHash::new(DelayedPublicMutableValues::new(value_change, delay_change));\n\n self.context.storage_write(self.storage_slot, values);\n }\n}\n\nimpl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, &mut PrivateContext>\nwhere\n T: Eq,\n{\n /// Returns the current value.\n ///\n /// If [`schedule_value_change`](DelayedPublicMutable::schedule_value_change) has never been called, then this\n /// returns the default empty public storage value, which is all zeroes - equivalent to `let t =\n /// T::unpack(std::mem::zeroed());`.\n ///\n /// It is not possible to detect if a `DelayedPublicMutable` has ever been initialized or not other than by testing\n /// for the zero sentinel value. For a more robust solution, store an `Option<T>` in the `DelayedPublicMutable`.\n ///\n /// ## Privacy\n ///\n /// This function does leak some privacy, though in a subtle way. Understanding this is key to understanding how to\n /// use `DelayedPublicMutable` in a privacy-preserving way.\n ///\n /// Private reads are based on a historical public storage read at the anchor block (i.e.\n /// [`crate::history::storage::public_storage_historical_read`]). `DelayedPublicMutable` is able to provide\n /// guarantees about values read in the past remaining the state variable's current value into the future due to\n /// the existence of delays when scheduling writes. It then sets the `expiration_timestamp` property of the current\n /// transaction (see\n /// [`PrivateContext::set_expiration_timestamp`](crate::context::PrivateContext::set_expiration_timestamp)) to\n /// ensure that the transaction can only be included in a block **prior** to the state variable's value changing.\n /// In other words, it knows some facts about the near future up until some time horizon, and then makes sure that\n /// it doesn't act on this knowledge past said moment.\n ///\n /// Because the `expiration_timestamp` property is part of the transaction's public information, any mutation to\n /// this value could result in transaction fingerprinting. Note that multiple contracts may set this value during a\n /// transaction: it is the smallest (most restrictive) timestamp that will be used.\n ///\n /// If the state variable **does not** have any value changes scheduled, then the timestamp will be set to that of\n /// the anchor block plus the current delay. If multiple contracts use the same delay for their\n /// `DelayedPublicMutable` state variables, then these will all be in the same privacy set.\n ///\n /// If the state variable **does** have a value change scheduled, then the timestamp will be set to equal the time\n /// at which the current value will change, i.e. the one\n /// [`get_scheduled_value`](DelayedPublicMutable::get_scheduled_value) returns - which is public information. This\n /// results in an unavoidable privacy leak of any transactions in which a contract privately reads a\n /// `DelayedPublicMutable` that will change soon.\n ///\n /// Transactions that do not read from a `DelayedPublicMutable` are part of a privacy set in which the\n /// `expiration_timestamp` is set to their anchor block plus [`crate::protocol::constants::MAX_TX_LIFETIME`],\n /// making this the most privacy-preserving delay. The less frequent said value changes are, the more private the\n /// contract is. Wallets can also then choose to further lower this timestamp to make it less obvious that their\n /// transactions are interacting with this soon-to-change variable.\n ///\n /// ## Examples\n ///\n /// A private action that requires authorization:\n /// ```noir\n /// #[external(\"private\")]\n /// fn do_action() {\n /// assert(\n /// self.storage.user_authorization.at(self.msg_sender()).get_current_value(),\n /// \"caller is not authorized\"\n /// );\n ///\n /// // do the action\n /// }\n /// ```\n ///\n /// A private action that can be paused:\n /// ```noir\n /// #[external(\"private\")]\n /// fn do_action() {\n /// assert(!self.storage.paused.get_current_value(), \"contract is paused\");\n ///\n /// // do the action\n /// }\n /// ```\n ///\n /// ## Cost\n ///\n /// This function performs a single merkle tree inclusion proof, which is in the order of 4k gates.\n pub fn get_current_value(self) -> T\n where\n T: Packable,\n {\n // When reading the current value in private we construct a historical state proof for the public value.\n // However, since this value might change, we must constrain the maximum transaction timestamp as this proof\n // will only be valid for the time we can ensure the value will not change, which will depend on the current\n // delay and any scheduled delay changes.\n let (value_change, delay_change, anchor_timestamp) = self.anchor_read_from_public_storage();\n\n // We use the effective minimum delay as opposed to the current delay at the anchor block's timestamp as this\n // one also takes into consideration any scheduled delay changes. For example, consider a scenario in which at\n // timestamp `x` the current delay was 86400 seconds (1 day). We may naively think that the earliest we could\n // change the value would be at timestamp `x + 86400` by scheduling immediately after the anchor block's\n // timestamp, i.e. at timestamp `x + 1`. But if there was a delay change scheduled for timestamp `y` to reduce\n // the delay to 43200 seconds (12 hours), then if a value change was scheduled at timestamp `y` it would go\n // into effect at timestamp `y + 43200`, which is earlier than what we'd expect if we only considered the\n // current delay.\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(anchor_timestamp);\n let time_horizon = value_change.get_time_horizon(anchor_timestamp, effective_minimum_delay);\n\n // We prevent this transaction from being included in any timestamp after the time horizon, ensuring that the\n // historical public value matches the current one, since it can only change after the horizon.\n self.context.set_expiration_timestamp(time_horizon);\n\n value_change.get_current_at(anchor_timestamp)\n }\n\n fn anchor_read_from_public_storage(self) -> (ScheduledValueChange<T>, ScheduledDelayChange<InitialDelay>, u64)\n where\n T: Packable,\n {\n let header = self.context.get_anchor_block_header();\n let address = self.context.this_address();\n\n let anchor_timestamp = header.global_variables.timestamp;\n\n let values: DelayedPublicMutableValues<T, InitialDelay> =\n WithHash::historical_public_storage_read(header, address, self.storage_slot);\n\n (values.svc, values.sdc, anchor_timestamp)\n }\n}\n\nimpl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, UtilityContext>\nwhere\n T: Eq,\n{\n pub unconstrained fn get_current_value(self) -> T\n where\n T: Packable,\n {\n let dpmv: DelayedPublicMutableValues<T, InitialDelay> =\n WithHash::utility_public_storage_read(self.context, self.storage_slot);\n\n let current_timestamp = self.context.timestamp();\n dpmv.svc.get_current_at(current_timestamp)\n }\n}\n"
|
|
2942
|
+
"source": "use crate::protocol::{\n delayed_public_mutable::{\n delayed_public_mutable_values::{unpack_delay_change, unpack_value_change},\n DelayedPublicMutableValues,\n ScheduledDelayChange,\n ScheduledValueChange,\n },\n traits::Packable,\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext, UtilityContext},\n state_vars::StateVariable,\n utils::WithHash,\n};\n\n/// Public mutable values with private read access.\npub struct DelayedPublicMutable<T, let InitialDelay: u64, Context> {\n context: Context,\n storage_slot: Field,\n}\n\n// DelayedPublicMutable<T> stores a value of type T that is:\n// - publicly known (i.e. unencrypted)\n// - mutable in public\n// - readable in private with no contention\nimpl<T, let InitialDelay: u64, Context, let M: u32> StateVariable<M + 1, Context> for DelayedPublicMutable<T, InitialDelay, Context>\nwhere\n DelayedPublicMutableValues<T, InitialDelay>: Packable<N = M>,\n{\n fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, PublicContext>\nwhere\n T: Eq,\n{\n\n pub fn schedule_value_change(self, new_value: T)\n where\n T: Packable,\n {\n let _value_change = self.schedule_and_return_value_change(new_value);\n }\n\n pub fn schedule_and_return_value_change(self, new_value: T) -> ScheduledValueChange<T>\n where\n T: Packable,\n {\n let mut value_change = self.read_value_change();\n let delay_change = self.read_delay_change();\n\n let current_timestamp = self.context.timestamp();\n let current_delay = delay_change.get_current(current_timestamp);\n\n // TODO: make this configurable https://github.com/AztecProtocol/aztec-packages/issues/5501\n let timestamp_of_change = current_timestamp + current_delay;\n value_change.schedule_change(\n new_value,\n current_timestamp,\n current_delay,\n timestamp_of_change,\n );\n\n self.write(value_change, delay_change);\n\n value_change\n }\n\n pub fn schedule_delay_change(self, new_delay: u64)\n where\n T: Packable,\n {\n let mut delay_change = self.read_delay_change();\n\n let current_timestamp = self.context.timestamp();\n\n delay_change.schedule_change(new_delay, current_timestamp);\n\n self.write(self.read_value_change(), delay_change);\n }\n\n pub fn get_current_value(self) -> T\n where\n T: Packable,\n {\n let current_timestamp = self.context.timestamp();\n let value_change = self.read_value_change();\n\n value_change.get_current_at(current_timestamp)\n }\n\n pub fn get_current_delay(self) -> u64\n where\n T: Packable,\n {\n let current_timestamp = self.context.timestamp();\n self.read_delay_change().get_current(current_timestamp)\n }\n\n pub fn get_scheduled_value(self) -> (T, u64)\n where\n T: Packable,\n {\n self.read_value_change().get_scheduled()\n }\n\n pub fn get_scheduled_delay(self) -> (u64, u64)\n where\n T: Packable,\n {\n self.read_delay_change().get_scheduled()\n }\n\n fn read_value_change(self) -> ScheduledValueChange<T>\n where\n T: Packable,\n {\n let packed = self.context.storage_read(self.storage_slot);\n unpack_value_change::<T, <T as Packable>::N>(packed)\n }\n\n fn read_delay_change(self) -> ScheduledDelayChange<InitialDelay>\n where\n T: Packable,\n {\n let packed = self.context.storage_read(self.storage_slot);\n unpack_delay_change::<InitialDelay>(packed)\n }\n\n fn write(\n self,\n value_change: ScheduledValueChange<T>,\n delay_change: ScheduledDelayChange<InitialDelay>,\n )\n where\n T: Packable,\n {\n let values = WithHash::new(DelayedPublicMutableValues::new(value_change, delay_change));\n\n self.context.storage_write(self.storage_slot, values);\n }\n}\n\nimpl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, &mut PrivateContext>\nwhere\n T: Eq,\n{\n pub fn get_current_value(self) -> T\n where\n T: Packable,\n {\n // When reading the current value in private we construct a historical state proof for the public value.\n let (value_change, delay_change, anchor_timestamp) = self.anchor_read_from_public_storage();\n\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(anchor_timestamp);\n let time_horizon = value_change.get_time_horizon(anchor_timestamp, effective_minimum_delay);\n\n // We prevent this transaction from being included in any timestamp after the time horizon.\n self.context.set_expiration_timestamp(time_horizon);\n\n value_change.get_current_at(anchor_timestamp)\n }\n\n fn anchor_read_from_public_storage(\n self,\n ) -> (ScheduledValueChange<T>, ScheduledDelayChange<InitialDelay>, u64)\n where\n T: Packable,\n {\n let header = self.context.get_anchor_block_header();\n let address = self.context.this_address();\n\n let anchor_timestamp = header.global_variables.timestamp;\n\n let values: DelayedPublicMutableValues<T, InitialDelay> =\n WithHash::historical_public_storage_read(header, address, self.storage_slot);\n\n (values.svc, values.sdc, anchor_timestamp)\n }\n}\n\nimpl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, UtilityContext>\nwhere\n T: Eq,\n{\n pub unconstrained fn get_current_value(self) -> T\n where\n T: Packable,\n {\n let dpmv: DelayedPublicMutableValues<T, InitialDelay> =\n WithHash::utility_public_storage_read(self.context, self.storage_slot);\n\n let current_timestamp = self.context.timestamp();\n dpmv.svc.get_current_at(current_timestamp)\n }\n}\n"
|
|
2939
2943
|
},
|
|
2940
2944
|
"84": {
|
|
2941
2945
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/state_vars/map.nr",
|