diff --git a/yarn-project/acir-simulator/src/client/private_execution.test.ts b/yarn-project/acir-simulator/src/client/private_execution.test.ts index 43a69221d78..ffe6c12abc7 100644 --- a/yarn-project/acir-simulator/src/client/private_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/private_execution.test.ts @@ -18,6 +18,7 @@ import { computeContractAddressFromPartial, computeSecretMessageHash, computeUniqueCommitment, + computeVarArgsHash, siloCommitment, } from '@aztec/circuits.js/abis'; import { pedersenPlookupCommitInputs } from '@aztec/circuits.js/barretenberg'; @@ -32,6 +33,7 @@ import { DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { AppendOnlyTree, Pedersen, StandardTree, newTree } from '@aztec/merkle-tree'; import { ChildContractAbi, + ImportTestContractAbi, NonNativeTokenContractAbi, ParentContractAbi, PendingCommitmentsContractAbi, @@ -641,7 +643,50 @@ describe('Private Execution test suite', () => { }); }); - describe('consuming Messages', () => { + describe('nested calls through autogenerated interface', () => { + let args: any[]; + let argsHash: Fr; + let testCodeGenAbi: FunctionAbi; + + beforeAll(async () => { + // These args should match the ones hardcoded in importer contract + const dummyNote = { amount: 1, secretHash: 2 }; + const deepStruct = { aField: 1, aBool: true, aNote: dummyNote, manyNotes: [dummyNote, dummyNote, dummyNote] }; + args = [1, true, 1, [1, 2], dummyNote, deepStruct]; + testCodeGenAbi = TestContractAbi.functions.find(f => f.name === 'testCodeGen')!; + const serialisedArgs = encodeArguments(testCodeGenAbi, args); + argsHash = await computeVarArgsHash(await CircuitsWasm.get(), serialisedArgs); + }); + + it('test function should be directly callable', async () => { + logger(`Calling testCodeGen function`); + const result = await runSimulator({ args, abi: testCodeGenAbi }); + + expect(result.callStackItem.publicInputs.returnValues[0]).toEqual(argsHash); + }); + + it('test function should be callable through autogenerated interface', async () => { + const importerAddress = AztecAddress.random(); + const testAddress = AztecAddress.random(); + const parentAbi = ImportTestContractAbi.functions.find(f => f.name === 'main')!; + const testCodeGenSelector = generateFunctionSelector(testCodeGenAbi.name, testCodeGenAbi.parameters); + + oracle.getFunctionABI.mockResolvedValue(testCodeGenAbi); + oracle.getPortalContractAddress.mockResolvedValue(EthAddress.ZERO); + + logger(`Calling importer main function`); + const args = [testAddress]; + const result = await runSimulator({ args, abi: parentAbi, origin: importerAddress }); + + expect(result.callStackItem.publicInputs.returnValues[0]).toEqual(argsHash); + expect(oracle.getFunctionABI.mock.calls[0]).toEqual([testAddress, testCodeGenSelector]); + expect(oracle.getPortalContractAddress.mock.calls[0]).toEqual([testAddress]); + expect(result.nestedExecutions).toHaveLength(1); + expect(result.nestedExecutions[0].callStackItem.publicInputs.returnValues[0]).toEqual(argsHash); + }); + }); + + describe('consuming messages', () => { const contractAddress = defaultContractAddress; const recipientPk = PrivateKey.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec'); diff --git a/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json b/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json index 40ba33f0262..6b9d14f4b01 100644 --- a/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json +++ b/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json @@ -152,7 +152,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "H4sIAAAAAAAA/+2dB3xcxdHA392p3qlLliXZliV3ud5TseR+LpgONr2DbWwgOKbZBEgIISShd0LvECCQACGEEELvPfQA6ZUUAoQe6rcrzaDR6lm2uVl59tO+3280+/budv8zuzu7997e07LcIGjOCTqPmJK4khxI43mucZ4H6dyujwXw8aBayWAlNUpqyefw9TolQ5QMVTIMXo+T1+uVDFfSoKSR1DdSSQE5H2WcjzbOxxjnY43zccZ5k3E+3jifYJxPNM4nGeeTjfMpxnnaOA+N82bjvMU4bzXO24zzqcZ5u3HeYZxPM86nG+czjPOZxvks43y2cT7HOM8Y53ON83nG+XzjfIFxvolxvtA439Q438w439w438I439I438o439o438Y439Y4X2ScLzbOtzPOtzfOdzDOdzTOdzLOdzbOdzHOdzXOdzPOdzfO9zDO9zTO9zLO9zbO9zHOlxjnS+Fcx4dE0NVf9KHjgB77erzrMa7H9biga/zqMavHqR6bejzqMajHnR5renzpMaXHkR47erzoMaLHhR4Luv/rPq/7ue7buj/rPjwH6tb9U/dJ3Q9139P9Tfcx3a90X9L9R/cZ3U9039D9QfeBbaGtF0Obbg9ttyO00c7QFruCz3cH3+4JPtwbfLUEfKL9o2NvA/hDx9vPgq6Yq3UN6FrQdaCHgB4KehjoetDDQTeAbgQ9AvRI0KNAjwY9BvRY0ONAN4EeD3oC6ImgJ4GeDHoK6DToEHQz6BbQraDbSHnLlOwb4Zup8J520B2gp4GeDnoG6JmgZ4GeDXoO6AzouaDngZ4PegHoTUAvBL0p6M1Abw56C9Bbgt4K9NagtwG9LehFoBeD3g709qB3AL0j8c1yJSuCnkcMdAZ0S3pqa+vy9ublYUu4JN08bWlHW7q1benUjrAjbOto27e5o6VleUdrR/u0pdPa09PC1pbl4Yq2aS0r0l3HfqSsdJaHTc79HeE8wBHOrzjCeaAjnCsd4fyqI5yrHOE8yBHOgx3hPMQRzkMd4TzMEc7VjnCucYTzcEc4v+YI5xGOcB7JyGl+J9PfefV3k51B7wJ6V9C7gd4d9B6g9wS9F+i9Qe8DegnopaD3A70/6ANAfwX0gaBXgv4q6FWgDwJ9MOhDQB8K+jDQq0GvAX046K+BPgL0kUH3d7KjlHw96Hlwt+E3Ajf62tGOcH7TEc5jHOH8liOcxzrC+W1HOI9zhPM7jnB+1xHO7znCebwjnCcE/Gu0MihPX0/Xa5XloI8C/Q3QR4P+JuhjQH8L9LGgvw36ONDfAf1d0N8DfTzoE4LuNdKJSk4Kuu79FARrPzI8Pgjtld1qs+xmi2W3WCy71WLZbRbLnmqx7PY8KEePxwZIn6zkFCWnKjlNyelKzlByppKzlJyt5Bwl31dyrpLzlJyv5AIlFyq5SMnFSi5RcqmSy5RcruQKJVcquUrJ1Up+oOQaJdcquU7JD5Vcb7DcoORHSn6s5EYlNym5WclPlNyi5KdKblXyMyW3Kfm5ktuV/ELJHUp+qeROJXcpuVvJPUruVXKfkvuVPKDkQSUPKXlYySNKHlXymJLHgeEJ0E+Cfgr000H38XRlly4E0Ud+0J2H8SSP5OHruSQPX88hefh6guTh63GSh6/HSB6+Hhj16yMDOp3lkRf0nmvSWR7a5gpiRxBhbyzCL/EI/+HruRH+o+2Br2O7lChJRdStP5PktTeMBT2PDEljXZQlIYglRxBLriCWPEEs+YJYCgSxFApiiW1kFhpT8dDj6flE9+u4XqdxuBzSNA5j7KZxuJKUiXlVxGbMGwRpOn8iYxnJQ9+Vk7wiSNO5oxjSlSSvBNJVJK8U0oMiWGjb4GcyoNPZHZ1tQ+vJkHOsK0kYBglgKRTEUiCIJV8QS54gllxBLDmCWBKCWOIGy9rWvjb46JEh6aoIloQglhxBLLmCWPIEseQLYikQxFIoiCUpiCUliKVIEEuxIJYSQSylglhsryM2hMX2d6Z1sUR9n6XfOen33kqDn36HLSJ5+F2zmOThd9ISklcN6VKSF4/gw7UM/W6Kawr6HRbndvpdF+dY+p0Y5zqsX3/uPfL9vQby6ff3WkjT7+91kKbf34eQMjFvKKTp9/dhkKbf3+shXUDykLGG5KEttSQPba4jeeibISQPfTiU5KGvh5G8wZCuj+CjfRY/kwGdzu7o7LO0ngw5x7ro9/x6ASyDBLGUCmIpEcRSLIilSBBLShBLUhBLoSCWAkEs+YJY8gSx5ApiyRHEkhDEEo9gGcrLkqZru4Aw0SND0nRtOISZRZdZZ8G+IRtgXx2xr9aCfcxlhrrMGgucDbxltut2GB6sfzs0kHZoZLZPlzGC1IVcWE+KvF5NOEYwt12M1Inl4jnlW1/WModYyx1irXCItdIh1iqHWAdvZFb+esPOmEzr1UdfMZmyjGRl6ZpzRjGXqcsYTfjRVmRPkddHEdtG83J0tu/IoKdP8Xw0qdfbz1qvtz/w9nv7vf3efm+/t9/b7+339nv7vf3efm+/t9/b7+339nv7vf0S7F/b73KYr7P3ucd2ZARLQhBLjiCWXEEseYJY8gWxFAhiKRTEkhTEkhLEUiSIpVgQS4kgllJBLGWCWMoFsVQIYqkUxFIliGWQIJZqQSyDBbHUCGKpFcRSJ4hliCCWoYJYhgliqRfEMlwQS4MglkZBLCMEsYwSxBLbyCxr++03vh4neXhdLUHyxkCa/v55LKTp75/HETsxrwnS9PfP4yFNf/88gaRRT4Q0/b3yJEjT3zpPhjT9nfQUSNPfU+MDoYeTPHw4cCPJQ39Q/6E/RpM89McYkof+GEvy0B/jSB76o4nkoT/Gkzz0B/UPXoeYSPKwv00iefi9fDLJw+/HU0gefk9Nkzz8voj+0Xbl5nS/ju+lfSeMKAfTdAxg3Rl8P8MYoPVkyDnWRX9LnhbAMkoQywhBLI2CWBoEsQwXxFIviGWYIJahgliGCGKpE8RSK4ilRhDLYEEs1YJYBgliqRLEUimIpUIQS7kgljJBLKWCWEoEsRQLYikSxJISxJIUxFIoiKVAEEu+IJY8QSy5glhyBLEkBLHEI1hs7OnE64D6wGt1owgHMk0mHJOYfaLLmBjBMYlwYP0TCccEXo7O/9s2PoJjAuHA+scTjiZejs7/8TYugqOJcGD99Pr6WF6OVl3GmAiOsYQD6x9DOJj3/Hb+77iRERyjCQfWP5JwNPNydP6fuZYIjmbCgfXj+9a2F7mFl63Pez5RLAlBLDmCWHIFseQJYskXxFIgiKVQEEtSEEtKEEuRIJZiQSwlglhKBbGUCWIpF8RSIYilUhBLlSCWQYJYqgWxDBbEUiOIpVYQS50gliGCWIYKYhkmiKVeEMtwQSwNglgaBbGMEMQyUhDLKEEsowWxjBHEMlYQyzhBLE2CWMYLYpkgiGWiIJZJglgmC2KZIoglLYglFMTSLIgltpFZ1vb7JXyd/palFdL0Ny9tkKa/l5kKafpbm3ZI09/pdEB6DMmbBmn6+6B4BDPed2sleXj/q43k4X2oqSQP7we1kzy8L9NB8vD+CDLpsialul9Hnjj5zHRI0994zYA0/Y3XTFIm5s2CNP2N12xI0994IQ/1B3JPJ3lo3wySh36YSfLQX7NIHvp1dgQL7bP4mQzodHZHZ5+l9WTIOdZFf280WwBLsyCWUBBLWhDLFEEskwWxTBLEMlEQywRBLOMFsTQJYhkniGWsIJYxglhGC2IZJYhlpCCWEYJYGgWxNAhiGS6IpV4QyzBBLEMFsQwRxFIniKVWEEuNIJbBgliqBbEMEsRSJYilUhBLhSCWckEsZYJYSgWxlAhiKRbEUiSIJSWIJSmIpVAQS4EglnxBLHmCWHIFseQIYkkIYokbLPRe4DSSh/fs6D1KvLdH72XiPUB6zxPvFdJ7o3MgTe+hxg0+eq+V3jPEtqT3FrGv0XuQOBbovUocq1i/Pl/bPXHkyYBOZ3f0eU+c3sc136dtm0nu/RZEfAZjM733i3MHvfebImViHv1tFebh2oDe+8X66PM9aX2osb4kycP6UiQP6ysieVhfcQQLbRv8TAZ0Orujs21oPRlyXkTsiUXw4eu0PdDOdbUH+o22B/1tJObhujGqPaj/sD7q577ag7Yb1kfbF+uj9eeR92RAp7M8qC9o/ci8Lt+iD6hvsY2orfT3cphXSmzDPFofaqyP+hHro/7G+mi7YH2035i+pW1PmfRn8btdBnQ6u6NZ14Xf0fDoKz6VE0b8zkt/Y1fJy9c5HisMFjzHulKEocQeS3tqLXXjESd1V1jwQ2D4AY+KCJaEIJYcQSy5gljyBLHkC2IpEMRSKIglKYglJYilSBBLsSCWEkEspYJYygSxlAtiiW1klqjvvHSdSdfiuP6ia/Aqwyadh/fO6Boc7+3RNTjeeywlefEIPlxXVZI8XN9UkTxcZwwieTjfV5M8nHexfv25K4p6s8YjWKsjbKJtiHVnQKezOzrbkNaTIedYF/1uXC2ApVwQS5kgllJBLCWCWIoFsRQJYkkJYkkKYikUxFIgiCVfEEueIJZcQSw5glgSgljiESxVvCydP0vCNaQ+cE1XRTiQiT4fi3ldno4ZHA2kXvqMsBrmttBl1EbYX0Psx/prSR6m6Xc47rbRMb3OaA89Vs7MsecPXWY9sx26bXE/sD6OIXbVE//ZqHeYUW+NUa9+D30u0zGEFT+bIO+5JKe7HS6ANN0Hjv1Bt91woy76XQ5fw/spDRZsxzoCKL+OpNH2BmJ7A/lMJbEd33Mlsb0p1f25EbzsnbfvG6GsOOEeQViZn1verMugz4PG8htJ3hiSxjiBn6G/7xlDOG3EK8qB9deQvHERnGMI51jjfZqziZezs/9RjhipF+tKkPfcTPrWONK3bLRzU9Dbf/R5RRN462zT43580PPo6zoUfc7KRF6WtK01xCTCj7Yie4q8Tp9ryf3M/1jQ85n/GXJOn9Hi7Wet19sfePtdsX9t+ySY42yf9xkmRrAkBLHkCGLJFcSSJ4glXxBLgSCWQkEsSUEsKUEsRYJYigWxlAhiKRXEUiaIpVwQS4UglkpBLFWCWAYJYqkWxDJYEEuNIJZaQSx1gliGCGIZKohlmCCWekEswwWxNAhiaRTEMkIQy0hBLKMEsYwWxDJGEMtYQSzjBLE0CWIZL4hlgiCW2EZmWdv+enx9MMnD6/b0+en4zOAmkhePqAOvqU8ieXhtG8vQ15dvLepdXzyivkkRXLZ9SevJkHOsi+5znySAZYIglvGCWJoEsYwTxDJWEMsYQSyjBbGMEsQyUhDLCEEsjYJYGgSxDBfEUi+IZZgglqGCWIYIYqkTxFIriKVGEMtgQSzVglgGCWKpEsRSKYilQhBLuSCWMkEspYJYSgSxFAtiKRLEkhLEkhTEUiiIpUAQS74gljxBLLmCWHIEsSQEscQNFr+3f90sfm9/NIvf2x/N4vf2R7P4vf3RLEWCWIoFsfi9/dEsfm9/NIvf2x/N4vf2R7P4vf3RLH5vfzSL39sfzeL39kez+L390SwNglgaBbGMEMTi9/ZHs/i9/dEsfm9/NIvf2x/NMkEQi+3r8hvCMlkQS2wjs6zrNw+TSV7c+Ky+Tv5GUffr+D8K4+Qz+L8M6f8gmwpp+j/I2kmZmIf/QzGP5OH/WsyPYKX/I3EKpOn/UkxDmv7PxRDS9H8zNkOa/g9H/N+I0yJYaBviZzKg09kdnW1I68mQc6yL/tZimgCWyYJYJglimSCIZbwgliZBLOMEsYwVxDJGEMtoQSyjBLGMFMQyQhBLoyCWBkEswwWx1AtiGSaIZaggliGCWOoEsdQKYqkRxDJYEEu1IJZBgliqBLFUCmKpEMRSLoilTBBLqSCWEkEsxYJYigSxpASxJAWxFApiKRDEki+IJU8QS64glhxBLAlBLPEIlnZelmZ6jyYgTPTIkDS9xzLVYNZ8bRZ8NdVgwXOsK0UYJlpjaU6nIuq2YHNzoWGzPvpqE3p/DO+fTSV803n5Otuk1WDBc6yL+mqKNZauNjHrtmBzc6Fhsz76ahOsX39uBqRbCd9MXr7ONplhsOA51kV9lbbIkoqo20I9zYWGzfroq02wfv25WZCeQfhmM/shRurBcvEc66K+Ci2ypCLqtlBPc6Fhsz76ahOsX39uDqRnEb4Msx9ipB4sd45RB/VVs0WWVETdFupppr7Fo682wbT+3FxIzyF885j9ECP1YLl4jnVRX7VYZEmtpW484qTuuRb8EBh+wGNuBEtCEEuOIJZcQSx5gljyBbEUCGIpFMSSFMSSEsRSJIilWBBLiSCWUkEsZYJYygWxVAhiqRTEUiWIZZAglmpBLIMFsdQIYqkVxFIniGWIIJahgliGCWKpF8QyXBBLgyCWRkEsIwSxjBTEMkoQy2hBLGMEsYwVxDJOEEuTIJbxglgmCGKZKIhlkiCWyYJYpghiSQtiCQWxNAtiaRHE0iqIpU0Qy1RBLO2CWDoEsUwTxDJdEMsMQSwzBbHMEsQyWxDLHEEsGUEssY3Msrbny+Dr9Bkr8yBNn88yH9L02S4LID2D5G0C6VkkbyGk55C8TSFdQfI2g/Rokrc5pOMkLx5hG+6jmUfycD/LfJKH+0oWkDzc37EJycN9FgtJHu532JTk4b6DzUge3v9Hdl1nYWVvm2ifwM9nQKezOzr7BK0nQ86xLvq8ms0FsGQEscwRxDJbEMssQSwzBbHMEMQyXRDLNEEsHYJY2gWxTBXE0iaIpVUQS4sglmZBLKEglrQglimCWCYLYpkkiGWiIJYJgljGC2JpEsQyThDLWEEsYwSxjBbEMkoQy0hBLCMEsTQKYmkQxDJcEEu9IJZhgliGCmIZIoilThBLrSCWGkEsgwWxVAtiGSSIpUoQS6UglgpBLOWCWMoEsZQKYikRxFIsiKVIEEtKEEtSEEuhIJYCQSz5gljyBLHkCmLJEcSSEMQSN1iS5PUykof7bOjzFBdCeirJw307rSTP3Juk83Af0CySNw/SuN/DPydo3Sz+OUHRLHmCWPxzgqJZCgWx+OcERbP45wRFs/jnBEWz+OcERbP45wRFs/jnBEWz+OcERbP45wRFs/jnBEWz+OcERbP45wRFszQIYmkUxDJCEIt/TlA0i39OUDSLf05QNEuTIJbxglgmCGLxzwmKZvHPCYpm8c8JimbxzwmKZvHPCYpm8c8JimbxzwmKZvHPCYpm8c8JimbxzwmKZskIYpkniGW+IJYFglg2EcSyUBDLpoJYNhPEsrkglthGZikM+n4OGX221haQXkjytoQ0fVbXVpCmz/TaGtL02V/bQHoeyYtH8OFeuy1IHu5525Lk4d6zrUge7gHbmuThXiysX39ud/I8sEWQHyefWQzpBMnbDtI5JG97Uibm7QDpPJK3I6TzSd5OkC4geci4iOShLYtJHtq8HclD32xP8tCHO5A89PWOJG9bSO8UwUf7LH4mAzqd3dHZZ2k9GXKOddHnpO0kgGVzQSybCWLZVBDLQkEsmwhiWSCIZb4glnmCWDKCWOYIYpktiGWWIJaZglhmCGKZLohlmiCWDkEs7YJYpgpiaRPE0iqIpUUQS7MgllAQS1oQyxRBLJMFsUwSxDJREMsEQSzjBbE0CWIZJ4hlrCCWMYJYRgtiGSWIZaQglhGCWBoFsTQIYhkuiKVeEMswQSxDBbEMEcRSJ4ilVhBLjSCWwYJYqgWxDBLEUiWIpVIQS4UglnJBLGWCWEoFsZQIYikWxFIkiCUliCUpiKVQEEuBIJZ8QSx5glhyBbHkCGJJCGKJR7CM4GVpp3Xq+vA72QhS5/bMddI9kAHxAz0yJL09YVnMy5LW9S4i5WdIHbTenXnrDWm9MRCsA/MTJH0DTjbkffrA/X3IrN+2XcT7aHoH4zMp8vp2lm1eTDgy5Bzr0rHgcmLrdhHcOxJufH0bwl3DzK3L2J5wYP30uUPM/bKd7ifGo68xspiwMLdb5xjZhZSfIXXQendl9jutF8cI1oH5CZK+m/SbXbuTX/QbZNZvWxTxPpo2x1CKvL7Iss10rGbIOdalx8hPia2LIri3J9z4+taE28YYoWMb66djhLlfttO9+Xj0NUZ2JizM7dY5RnYj5WdIHbTe3Zn9TuvFMYJ1YH6CpJ8l/Wb37uQX/QaZ9dt2iXgfTZtjKEVe38WyzXSsZsg51qXHyMPE1l0iuOn8h69vRbhtjBE6trF+OkaY+2XnGKG266OvMbIrYWFut84xsgcpP0PqoPXuyex3Wi+OEawD8xMk/VfSb/bsTn7Rb5BZv223iPfRtDmGUuT13SzbTMdqhpxjXXqMvEJs3S2Cm85/+PqWhNvGGKFjG+unY4S5X3aOEWq7PvoaI7sTFuZ26xwje5HyM6QOWu/ezH6n9eIYwTowP0HSH5B+s3d38ot+g8z6bXtEvI+mzTGUIq/vYdlmOlYz5Bzr0mPkdWLrHhHcdP7D17cg3DbGCB3bWD8dI8z9snOMUNv10dcY2ZOwMLdb5xjZh5SfIXXQepcw+53Wi2ME68D8BEknyQ97l3Qnv+g3yKy7114R76NpcwylyOt7WbaZjtUMOce69Bj5nIyRvSK46fyHr88l3DbGCB3bWD8dI8z9snOMUNv10dcY2ZuwMLdb5xhZSsrPkDpovcuY/U7rxTGCdWB+gqSHkTGyrDv5Rb9BZt299ol4H02bYyhFXt/Hss10rGbIOdalx0gFsXWfCG46/+Hr2xJuG2OEjm2sH+spJBz0Gf424yqWi+e0LcsMf1lgaU9F1K3bblyqO92UstsmWL8+6iLaBPP2IXxnwk0UPbbwvsEU4CyGz+E9QvrMgiQpA/Owm9JnFtD/+YF5eI+aPrMA76HTZxbESRo1MiRJHjKkSB4yFJE8ZCgmechQQpjW9lwN5MmATmd39PlcDWq7+T5t24GVvW2NR9iaiLCVtlmclIl59H9SYR5+Jj+iPOqjPMOWdHZHp49oPZmg5/9A0gd9jgN9LZeVpTlN/RoYtgdGXUHQ839YFbCypNN5Qfe44CoTfRkQ7oCwp4Ke4w7fk+Tl6GzzgqCnT/Gc/m8lbz9rvd7+wNvv7ff2e/u76/D2e/u9/d5+b7+339vv7ff2e/u9/d5+b7+339vv7ff2e/u9/d5+b7+3P+Pt9/b3o/289Xbtb6D16qOv/Q2UJcXKYm9/QxHhp+2Kmu4XQtuKeDk62zdl+BTP6X4pbz9rvd7+wNvv7ff2e/u9/d5+b7+339vv7ff2e/u9/d5+b7+339vv7ff2e/u9/d5+b7+339vv7ff2e/s3jv0p3no79zfQ8tHOYsMfOq/E8I3Ow/85Eid5ZZCmz9nA/9kS9ZwN6l/8DH0eCX6mhOThcyRKSR7yl5E8fPYF1p8fWOlHzRu6T6SQaNwzgp+30M6d/StpsOA57esFxE92WMLO5wKZdScj/JAkr1Pf8I69sF2XWcJcJh1DePTVH+izftDW/Zav3uag1csPi5HPY5n4v8TySRlx8r5E0LvunKD3kUvSeSRdRD6XMuqk456OU6y/lLDlkXIzoNPZHc10/FP76JGJsIvGA4vPoenxfB4sF8/p/IIMCXssbamIupNr8QP33EpjIpat++B9Rd11Mse5Nv6x3PX8P7pGOIbYVUL8Z6PeYqPelFEvjet58B5kxc8myHueKupuh8cgnSTl0WdelRp1rW2MJ8k5HZdlJI3+ojGogqTjxmd0meXG+7R9+D/xMqDT2R1thQaHPvqKJZWEZRAvS2d7V5PyM6QOWu9g3npDWi8+ZxLrwPwESf+RDIbB3ckv+gAy6zasingfTVcYn0mR16ss2zyIcGTIOdal++qLxNaqCG4az/H1csJdxcyty6gkHAUGWyGxg8b26n70XzXxSa7hLwssnXOcWbct3w9ah+8xD99nznc5vEzN9DsTHn3FrxziH951Wdde+S+zLtM6n5Wla68881qq81pBIeFHW5E9RV6n31eY11V9ri/pNQpvP2u93v7A2+/t9/Z7+7393n5vv7ff2+/t9/Z7+7393n5vv7ff2+/t9/Z7+7393n5vv7ff2+/t9/Z7+/vf/kKSl9jILCnCYG+/ZXM6FUT3A2abmwsNm/WxPnvd+fd7du05SW4AS4qwMP+Gw9qeE7oHFG0tIvaYv9XII3kZHo7Q3AObCXrvM/X2e/u9/az1evsDb7+339vv7ff2e/u9/d5+b7+339vv7ff2e/u9/d5+b7+339vv7ff2e/u9/d5+b7+3f+PYX0jy8jcyC90LkrTG0rXnJKofMNvc2Q9KiM1xo84k4bD3TK4ue00GXU8paz1dbUyPDEljXZQlIYglRxBLriCWPEEs+YJYCgSxFApiSQpiSQliKRLEUiyIpUQQS2wjsxQGvfeBFpLX6TOnyyDd13MudR7Osfh+Pbesqex+HZ/7FyefwefeJSLqK4/gqoj4LPUlfiYDOp3d0elLWk+GnGNdScJQIYClRBBLsSCWIkEsKUEsSUEshYJYCgSx5AtiyRPEkiuIJUcQS0IQSzyChfv6B11fYNm6PW4s6a6T93m34QpdJvNzl9Pmc4OPIXYNJv6zUW+1Ua/5bGr9Hvqc7WOC3s8VTpD3vFbR3Q63QTskSXn0mkwtrz2dzyKuC7oP7INYj+aogXQd4eiv62F1rPX0vebHutZ2PWxjs+QIYskVxJIniCVfEEuBIJZCQSxJQSwpQSxFgliKBbGUCGIpFcRSJoilXBBLhSCWSkEsVYJYBgliqRbEMlgQS40gllpBLLGNzLK2eyL4eg3JGwLpqHsitDz8noXvN++JDIV8ek9kGKQTEfUNjeAaFvFZ6kv8TAZ0Oruj05e0ngw5x7roPZFhAlhqBbHUCGIZLIilWhDLIEEsVYJYKgWxVAhiKRfEUiaIpVQQS4kglmJBLEWCWFKCWJKCWAoFsRQIYskXxJIniCVXEEuOIJaEIJZ4BAv3PWpdRn3QfeD3yCrCgUz1Fjl0mcNZy+x6tiW1Df1NjwxJDyf2NbKydN0/H0HKz5A6aL0jeesNab0xEKwD8xMkfRAuyMj79IHfA5FZ94uGiPfRdL3xmRR5vcGyzY2EI0POsS4dc/YltjZEcFcRbnydXl/BdqP3yhss2DI86GnLcIOZPh+33hpL114Fs24LNjfrMmj7xY06k4SjkXD0194M5tjQ57VHOnbwSAhiyRHEkiuIJU8QS74glgJBLIWCWJKCWFKCWIoEsRQLYikRxFIqiKVMEEu5IJYKQSyVgliqBLEMEsRSLYhlsCCWGkEstYJY6gSxDBHEMlQQyzBBLPWCWCxe99tglgZBLLGNzLK2/VbmdVOdh9cvo/Zb0fLw2gm+39xvhdcH4+QzoyCdiKhvZATXqIjPUl/auN5J68mQc6yL7rcaJYClQRDLcEEs9YJYhgliGSqIZYggljpBLLWCWGoEsQwWxFItiGWQIJYqQSyVglgqBLGUC2IpE8RSKoilRBBLsSCWIkEsKUEsSUEshYJYCgSx5AtiyRPEkiuIJUcQS0IQSzyCxcazhbBO+myhzcu667SxX3Icsx3aj2OC7uMYYtc44j8b9Y4Nug/6bCGsS79nNKTz4D3Iip9NkPc8RJ4ttBjaIUnKo3tixkM6w2NPiy5jQtB9YB/EejRHE6QnEI7+2r82gbWevq/lYl1r27+2sVlyBLHkCmLJE8SSL4ilQBBLoSCWpCCWlCCWIkEsxYJYSgSxlApiKRPEUi6IpUIQS6UglipBLIMEsVQLYhksiKVGEEutIJY6QSxDBLEMFcQyTBBLvSCW4YJYGgSxNApiGSGIZaQgllGCWEYLYhkjiGWsIJZxgliaBLGMF8QS28gsa9s3jK83kbyJkI7aN0zLw2vW+H5z3/AkyI+Tz0yGdCKivkkRXJMjPkt9iZ/JgE5nd3T6ktaTIedYF903PFkAy3hBLE2CWMYJYhkriGWMIJbRglhGCWIZKYhlhCCWRkEsDYJYhgtiqRfEMkwQy1BBLEMEsdQJYqkVxFIjiGWwIJZqQSyDBLFUCWKpFMRSIYilXBBLmSCWUkEsJYJYigWxFAliSQliSQpiKRTEUiCIJV8QS54gllxBLDmCWBKCWOIRLDaeeT0l6D7wmjx95jUyTbHIoctMs5bZ9cxrahv6mx4Zkk4T+5pZWbp+19FCys+QOmi9rbz1hrTeGAjWgfkJkj4YF6rkffrAa+rIrPtFGPE+mp5ifCZFXg8t29xMODLkHOvSMWc5sTWM4KbPvMbX6b0qbDe6Jz+0YEs66GlL2mBOEYYp1li6fkNj1p0keQmSF0b4poWVJ93ZlLS/YbxsIRxmu6ci3m+rD9IjQ9JRLAlBLDmCWHIFseQJYskXxFIgiKVQEEtSEEtKEEuRIJZiQSwlglhKBbGUCWIpF8RSIYilUhBLlSCWQYJYqgWxDBbEUiOIpVYQS50gliGCWIYKYhkmiKVeEMtwQSwNglgaBbGMEMQyUhDLKEEsowWxjBHEMlYQyzhBLE2CWMYLYpkgiGWiIJZJglgmC2KZIojF9v3JDWGxfd9wQ1iaBbG0CGKJbWSWqN886vtIB5LfKLZDfpx8pgPS9DeK0yCdQ/KwnnaS1wbpDpI3FdLTIsqjPuowbElnd3T6iNaTIedYF/0t4zQBLC2CWJoFsYSCWNKCWKYIYpksiGWSIJaJglgmCGIZL4ilSRDLOEEsYwWxjBHEMloQyyhBLCMFsYwQxNIoiKVBEMtwQSz1gliGCWIZKohliCCWOkEstYJYagSxDBbEUi2IZZAglipBLJWCWCoEsZQLYikTxFIqiKVEEEuxIJYiQSwpQSxJQSyFglgKBLHkC2LJE8SSK4glRxBLQhBL3GCh9xbTJA/vH4Ykbzqkm0neDEjT+5szId1G8mZBeirJixt89Pmt9P4ltuV0kod9bQbJw7Ewk+ThWMX69XnSOA/gs7WQzoBOZ3eElEUfeB2uluRNJ+kRBn+S2DedcLazcnb9Fp1y6KOve9nthGU2K0vXb9HnkPIzpI52I5+x3pDWGwu6x1BA8hMk/Qp+EQh6+gb7FTLrNuyIeB9NTzc+kyKvd1i2ebbBZLanHntPE1s7IrhHEm58fQbhtjGu2gmHOa5oTKPjm7mvdvqvw/AfntO2zDf8xc/S9ft3s25bvu9Yh+8xD99H/8dqkvAlLHPOIZzlBqc+5pI0fn/FzyQJy1zCOY+Vsyv2Ug599BV75xGWBawsXbF3E1J+htRB613IW29I68XYi3VgfoKkPybxaGF38ot+hcy6DedHvI+m5xqfSZHX51u2eQHhyJBzrEuPm7eIrfMjuMsJ93yD0da4mkc4zHFVSDjo+Gbuq53+m2/4D89pWyYMf/GzdMVes25bvp+/Dt9jHr5P96EbS7r9gUeccKaYOfuKX6mgN0tCEEuOIJZcQSx5gljyBbEUCGIpFMSSFMQS28gsa/s/N/h6nOThdXG6zxuv29N93nhfIZfk0ediYB6ua/NJHs4RBSSvgqRR4323JMmLR9iGrEUkD1mLSR6ylpA8ZC0lechaRvKQtZzkIStlR1Zk13VeVdnbJton8PMZ0Onsjs4+QevJkHOsi+5xrxTAkhTEUiiIpUAQS74gljxBLLmCWHIEsSQEscQNlnzgKWDmofMCnd8wvtG5FucwOtfiHEbnWpzD6FxLn4eFeaXENsyj9aGmz6LEPKyPzqtYH51XsT46r2J9dF5F2ylTHuHJgE5nebhSJvVnPMKf8Qh/0jxM0z5Av7diXg7xN/V7Dqc9YZc9WC/tv8iHR1/r07w+bM4LuvtshoM53XV9kX4vyAQ9v7OgtrFGTxJ/xEgdSeJDTJ9Q2f1efJ9uv8+In3JIeUXEd58Zn8H3FJA0LQc/a6ZpPwugTHydlpW/Dr488rkM6HR2R6c/CwlrhpzT+Pn1ym6GfF6GZurTHCgX+1C+PdvTtE9gHzbbRecXW/A51ot9GOug8ximL8WJlrxPH+acQteVdE6JGpc2bCokNmXIeTHJX9t76HiJsrGQ2JiMeF9ffkmR15PrWQ/9DO2DNvxGbc+Qc3qt4GTyvbcwgpnGYsxbn/UK7qEwr1/QfX30M+b1C7ovMpfkmdcv6L7SqOsXdK6ysa4lj2DvLBfPsa5U0Pt6CD9L1/0Fs27qh4S1utffD+Y1oI3hhxxrda+/H8zrXjZY1uWHXAF+QIaCjeiHPAF+oLF1Y/khX4AfkCHZz37Q9ZrfgVhvyOKRMMpuSU9tbV3e3rw8bAmXpJunLe1oS7e2LZ3aEXaEbR1t+zZ3tLQs72jtaJ+2dFp7elrY2rI8XNE2rWUFFB5n5HySketXfFzpRFTjkDwu+zmZKe8zJI2BPx7RJ/Is2BQY9Zh+LAksd3wbjfSMhXKfDfg6vy27n+VvI/qPecT7FA/mq37h04yczzGW1V+B77nATuB7nqR94MuyzOfAodzlvhDIDnza7hf428hq4OP0aX8FgacCO0HgRZL2QSDLMp8Ch3KX+1IgOwhou1/ib6O02UGMssN0FsfJJmcWpZ3C2D5b5fSb/9LZWH1qEMH5JUs7jdF/W/ev/9Jf1urTg7VwfonSzmD03zb977/0l7H6zKAPzg0s7SxG/227cfyX3lCrzw7WwbkBpZ3D6L9FG89/6Q2x+vvBenCuZ2nnMvpv8cb1X3p9rT4vWE/O9SjtfEb/bbfx/ZdeH6svCDaAcx2lXcjov+1l+C+9LqsvCjaQs4/SLmb03w5y/Jfuy+pLgi/BuZbSLmX0346y/Jdem9WXBV+SM6K0yxn9t5M8/6WjrL4iyILTKO1KRv/tLNN/adPqq4IsOUlpVzP6bxe5/ktTq38QMHBCadcw+m9X2f5Lo9XXBkycqrTrGP23m3z/6SP8IWNZ9JpTtv7b3RH/MV4nCrdh9N8ejviP8TpHuIjRf3s64j/G7+nhdoz+28sR/zF+zwx3YPTf3o74j/F7UrgTo//2ccR/jOv8cBdG/y1xxH+M69RwN0b/LXXEf4zrrHAPRv8tc8R/jOuEcC9G/+3riP8Y57lwH0b/LXfEf4xxOlzK6L8VjviPMc6E+zL6bz9H/Mc4TsIVjP7bv5/8ly3nrxnbgrHPhPv3X//Lav/VDQHf/qsfMbbr9xzZf/XjgG//1Y2M/jvekf1XNwV8+69uZvTfCY7sv/pJwLf/6hZG/53oyP6rnwZ8+69uZfTfSY7sv/pZsB6c61nabYz+O9mR/Vc/D9aTcz1Ku53Rf6c4sv/qF8EGcK6jtDsY/XeqI/uvfhlsIGcfpd3J6L/THNl/dVfwJTjXUtrdjP473ZH9V/cEX5IzorR7Gf13hiP7r+4LsuA0Sruf0X9nOrL/6oEgS05S2oOM/jvLkf1XDwUMnFDaw4z+O9uR/VePBEycqrRHGf13jiPXTx9jLOt7jNdPv++I/xivE4UnMPrvXEf8x3idIzyJ0X/nOeI/xu/p4SmM/jvfEf8xfs8MT2P03wWO+I/xe1J4BqP/LnTEf4zr/PAsRv9d5Ij/GNep4TmM/rvYEf8xrrPCcxn9d4kj/mNcJ4TnM/rvUkf8xzjPhRcy+u8yR/zHGKfDixn9d7kj/mOMM+GljP67whH/MY6T8HJG/13pyP6rlxnbgrHPhJz+08/p0g9ew+dw6z1n+v+DXA/6ZdCPg34CtD5eUfJq0PWsL/q/eJ6G97xC3vsbJb8Neh7c7fU7xvZycb9ctv77/QDs778z+vvv++jvf1Dyxz76+x/Ie/+k5M8R730S3vMn0PqBiH9R8teI9z4F7/kLaN3ef1Py96DnEWfuB5zPAnyNsU+hf/B/JlSDXwaDrgFdC7oO9BDQQ0EPA10PejjoBtCNoEcQ/Q8l/wRfx4nvuZ9z+A++stINUM6/lPxbyetK/qPkDSVvKnlLyX+VvK3kHSXvKnlPyftKPlDyoZL/KflIycdKPlHyKfjkczA+piSuJKEkR0mukjwl+UoKlBTCPyGKgd80S0HQff5v4/x14/w/xvkbxvmbxvlbxvl/jfO3jfN3jPN3jfP3jPP3jfMPjPMPjfP/GecfGecfG+efGOefGuefGeefG+c6Qc9jxnncOE8Y5znGea5xnmec5xvnBcZ5Yaz7f3vgwb3OpWMm23j1L8ay7hU+7y9foY90+G+msnRbvM7ov/vE+6+z6PA/2ZfVDDaHbzD6737J/mv9gjN8M7uy0sTm8C1G/z0g1X/NPTjD/375stKGzeHbjP57UKD/pq7oxRm+8+XK6oiwOXyX0X8PSfNfRyRn+N6Gl9W+FpvD9xn997Ak/7WvlTP8YMPKau7D5vBDRv89IsV/7X1yhv9b/7KWrcPm8CNG/z0qwX/t6+QMP16/stLrYXP4CaP/HtvY/kuvF2f46brLaltPm8PPGP33+Mb0X+t6c4af91lW64oNsDnUXzy5/PfExvJf+wZxhrG129yxgTaHcUb/PbkR/DdtxQZzholom9NfwuYwh9F/T/W3/9JfijPM7W1z+CVtDvMY/fd0f/pv3y/NGeb3tLklC5vDAkb//aqf/Ne8IivOsDDGdy3xXsb73M84sk+A8TpbeD+j/551xH+M14nCBxn995wj/mO8zhE+zOi/5x3xH+P39PBRRv+94MrvrBj99zij/150xH+M35PCJxn995Ij/mNc54dPM/rv1474j3GdGj7D6L+XHfEf4zorfI7Rf6844j/GdUL4AqP/XnXEf4zzXPgSo/9+44j/GON0+DKj/37riP8Y40z4KqP/fueI/xjHScjYZ0JO/8XAbw1QHu5rw/1uuA8O98fhvjncT4f77L7Yf4f74kDjPj7c34f7/nA/IO4TxP2DuK8Q9xviPkTcn4j7FnE/I+5zxP2PuC8S90viPkrcX4n7LnE/Ju7TxP2bDeCHpOJPKSlSUqykREmpkjIl5UoqlFQqqVIySEm1ksFKapTUKqlTMkTJUCXDlNQrGa6kQUmjkhFKRioZpWS0kjFKxioZp6QJ9pVSnpPh/BTQp4I+DfTpoM8AfSbos0CfDfoc0N8HfS7o80CfD/oC0BeCvgj0xaAvAX0p6MtAXw76CtBXgr4K9NWgfwD6GtDXgr4O9A9BX2/44QY4/xHoH4O+EfRNoG8G/RPQt4D+KehbQf8M9G2gfw76dtC/AH0H6F+CvhP0XaDvBn0P6HtB3wf6ftAPgH4Q9EOgHwb9COhHQT8G+nHQGfDDSDgfBXo06DGgx4IeB7oJ9HjQE0BPBD0J9GTQU0CnQYegm0G3gG4F3QZ6Kuh20B2gp4GeDnoG6JmgZ4GeDXoOsVfruaDngZ4PegHoTUAvBL0p6M1Abw56C9Bbgt4K9NagtwG9LehFoBeD3g709qB3AL0j6J1A7wx6F9C7gt4N9O6g9wC9J+i9QO8Neh/QS0AvDXrHKX2eAl0Euhh0CehS0GWgy0FXgK4EXQV6EOhq0INB14CuBV0HegjooaCHga4HPRx0A+hG0CNAjwQ9CvRo0GNAjwU9DnQT6PGxoMeBpxnQ6eyOcDzjfacE4bPJXB/wrg/wmEBOckDHyeu4/sqzYFNg1GP6sSQij7VyG400IcZf7kTGDmvL7okx9jbqHFyJoPcheXDZ5KxzhLM64A9WMVLmJHUyWckUJfoN+td2zUpalLQqaVMyVUm7kg4l05RMVzJDyUwls5TMVjJHjyslc5XMUzJfyQIlmyhZqGRTJZsp2VzJFkq2VLKVkq2VbKNkWyWLlCxWsp2S7ZXsoGRHJTsp2VnJLkp2VbKbkt2V7KFkTyV7KdlbyT5KlihZqmSZkn2VLFeyQsl+SvZXcoCSryg5UMlKMs5KQRcGvYN3IRk7MZJHg7s+8kg6w9RmFiaLtP4RbAGxIzDsLQFb8ljrbU3runKDnoc5KWUi/Nm5AIP0siUrVy469IDDl6xevnDNqmWrDzhoFe3WuUYxiQjzzPwc4op8SOeSPPxcPtExkz8DOts5hc5P6eyOsL9i/pSYnVga8HI2Wyw7pJ3rq+DgVaRz4ziLB90dKo+0B7aT7oyfB73bKkbScXhPoo/3xNZSDh3v+Hkc78w+sRK7rC5kY+Bc3YCfBt2/Zl0V610p99XUKQwL065fdq5Y8VXGRe4qxsHdXwEp7QNSj4B0EDj4YB+Q3AxIBxkB6eB+CEhpxoB0EGNAOtjBgBT6gNQjIB0CDj7UByQ3A9IhRkA6tB8CUsgYkA5hDEiHOhiQ2nxA6hGQDgMHr/YByc2AdJgRkFb3Q0BqYwxIhzEGpNUOBqSpPiD1CEhrwMGH+4DkZkBaYwSkw/shIE1lDEhrGAPS4Q4GpHYfkHoEpK+Bg4/wAcnNgPQ1IyAd0Q8BqZ0xIH2NMSAd4WBAWukDUo+AdCQ4+CgfkNwMSEcaAemofghIKxkD0pGMAekoS4Ob2390e1e2Nk9i9N/XmQN6r84f8Ad0TmbK+w1y4vehZlmmbqRvxPjLPZqx89uy++gYexv1CE5xo2zOvVPZlvXNmOx+qdvmmzH+/WefOPLjQ862PoaxrT9h/CFof01Ex1iaiL7lJyLeRvqWhYnoWOETkbb7WMsTkXSfBqQjc3LSH0FkyzmZ0eZvO7ia/7alIHqcD6K8jXSchSD6HeFBVNv9nQG8mv+u8NW8bpvvWljNfzYAV/PfY2zrzxxczX/P0kR0vJ+IeBvpeAsT0QnCJyJt9wmOrea5fRqQjszJSX8qnC1nB6PNJzq4mj/RUhA9yQdR3kY6yUIQPVl4ENV2nzyAV/OnCF/N67Y5xcJqXv8q3UZbS17Nn8rZ1rnureZPtTQRneYnIt5GOs3CRHS68IlI2326Y6t5bp/iwT1hHsXIeUbMzuCVvEg4U/giQbfJmRYWCfEBuEg4i7Gt4w4uEs6ytEg42y8SeBvpbAuLhHOELxK03ec4tkg4x5FFwmpGzu8PwEXCucIXCbpNzrWwSMgZgIuE8xjbOsfBRcJ5lhYJ5/tFAm8jnW9hkXCB8EWCtvsCxxYJFziySDickfPCAbhIuEj4IkG3yUUWFgl5A3CRcDFjW+c5uEi42NIi4RK/SOBtpEssLBIuFb5I0HZf6tgi4VJHFglHMHJeNgAXCZcLXyToNrncwiKhYAAuEq5gbOsCBxcJV1haJFzpFwm8jXSlhUXCVcIXCdruqxxbJFxlaZFgBtGs7y0z2tzMaPPVjAGpv4Lo1ZaC6A98EOVtpB9YCKLXCA+i2u5rLAdRyav5a4Wv5nXbXGthNZ8cgKv56xjbOungav46SxPRD/1ExNtIP7QwEV0vfCLSdl/v2Gqe26cB6ciUM9uyGf9Va9jCaPMNDq7mb7AURH/kgyhvI/3IQhD9sfAgqu3+8QBezd8ofDWv2+ZGC6v5ogG4mr+Jsa2LHFzN32RpIrrZT0S8jXSzhYnoJ8InIm33TxxbzXP6VLPpAYIDSD8z77Og6/8La30w6ENBJ5XcotI/hb5C/yl7M7ynBXQr6NWgDwd9BOhyJbeq9M8iytoX3rMc9ArQ+4HeH/QBoIuU3KbSPydlYSPcCu/pAD0N9HTQM0DPBD0L9GzQc0BnQM8FPQ/0fNALQG8CeiHoTUFvBnpz0FuA3hL0VqC3Br0N6G1BLwK9GPR2oLcHvQPoHUHvBHpn0LuA3hX0bqB3B70H6D1B7wV6b9D7gF4CeinoZaBvA/0V0AeCHq/kdpX+BWkbDM6T4D23gL4ddIWSO1T6l0YUlbyou5Nxou+vyXl4YGdyvstPzryNdJeFyflu4ZOztvtuC5Nzf/1/HM7BZZNziCOcgwP+YBUjZd6jTu5Vcp+S+5U8oORBJQ8peVjJI0oeVfKYkseVPKHkSSVPKXlaya+UPKPkWSXPKXleyQtKXlTykpJfK3lZyStKXlXyGyW/VfI7Jb9X8gclf1TyJyV/VvIXJX9V8jclf1fympJ/KPmnkn8p+beS15X8R8kbSt5U8paS/yp5W8k7St5V8p6S95V8oORDJf9T8pGSj5V8ouRTPemScVYKWv/PIDN4Fwa9//9QYdAzuOvDlf8rpL5QBwXEjsCwF/9HUh5rva1pXVdu0PMwJ6VMhD81ayWkly1ZuXLRoQccvmT18oVrVi1bfcBBq2i3zjWKSUSYZ+bnEFfkQzqX5OHn8omOmfwZ0NnOKXczL6j6I+bfF7MTSwNezn77n2ifo4NJpv+faDxl9sv/RNMNSP8nmv5jVsp9+fU+hoUp/k+0zzkXuXH3FqH3+4DUIyDF4CTuA5KbAUk3IA1I8X4ISPczBqRYnC8gxR0MSA/4gNQjICXgJMcHJDcDUsIISDn9EJAeYAxICcaAlONgQHrEB6QeASkXTvJ8QHIzIOUaASmvHwLSI4wBKZcxIOU5GJAe9QGpR0DKh5MCH5DcDEj5RkAq6IeA9ChjQMpnDEgFDgakx3xA6hGQCuEk6QOSmwGp0AhIyX4ISI8xBqRCxoCUdDAgfeYDUo+AlIKTIh+Q3AxIKSMgFfVDQPqMMSClGANSUdzO4Ob2H93ela3N9zDepSxmDui9On/AH9A5mSlvCQmIfh9qlmXqRiqJ85dbyhg8bNldGmdvI6u/VuTc21sWl90vdduUxfn3n5U48mtFzrYuZ2zrEgd/rVhuaSKq8BMRbyNVWJiIKoVPRNruSssTkXSfBqQjc3LSH0Fky3kvY0CucnA1X2UpiA7yQZS3kQZZCKLVwoOotrt6AK/mBwtfzeu2GWxhNV82AFfzNYxtXebgar7G0kRU6yci3kaqtTAR1QmfiLTddY6t5rl9GpCOzMlJfyqcLefjjAF5iIOr+SGWguhQH0R5G2mohSA6THgQ1XYPG8Cr+Xrhq3ndNvUWVvMVA3A1P5yxrSscXM0PtzQRNfiJiLeRGixMRI3CJyJtd6Njq3lun+LBPWEWMXKOiNsZvJIXCSOFLxJ0m4y0sEioGoCLhFGMbV3l4CKB0f4ei4TRfpHA20ijLSwSxghfJGi7xzi2SOD2KR7cE2YeI+fYAbhIGCd8kaDbZJyFRUL1AFwkNDG2dbWDiwRG+3ssEsb7RQJvI423sEiYIHyRoO2e4NgigduneHBPmAWMnBMH4CJhkvBFgm6TSRYWCTUDcJEwmbGtaxxcJDDa32ORMMUvEngbaYqFRUJa+CJB2512bJHA7VM8uCfMJCNnOAAXCc3CFwm6TZotLBLqBuAioYWxrescXCQw2t9jkdDqFwm8jdRqYZHQJnyRoO1uc2yRwO3TgHRkypn1o7cZbX6QMSBPZQxI/RVEp1oKou0+iPI2UruFINohPIhquzssB1HJq/lpwlfzum2mWVjNDx2Aq/npjG091MHV/HRLE9EMPxHxNtIMCxPRTOETkbZ7pmOreW6fBqQjU86sf1rBaPNDjAF5loOr+VmWguhsH0R5G2m2hSA6R3gQ1XbPGcCr+Yzw1Xxn/7Gwmq8fgKv5uYxtXe/gan6upYlonp+IeBtpnoWJaL7wiUjbPd+x1TynTzWbHiA4gO5VGZ/pRLxLx0HngE4qWaDSm0Bfof+U/UH47EOgHwadB58twDJAlytZqNKbRpT1Pnz2A9Afgv4f6I9Afwy6SMlmqpzNSVnYCAuhvsfhvU+AfhL0U6CfBv0r0M+Afhb0c6CfB/0C6BdBvwT616BfBv0K6FdB/wb0b0H/DvTvQf8B9B9B/wn0n0H/BfRfQf8N9N9Bvwb6H6D/CfpfoP8N+nXQ/wH9Bug3Qb8F+r+g3wb9Duh3Qb8HejPw8ydw/ino8Uq2UK9tSdoGg/M98J4F8NktQFco2Uqlt453vXd9/p1F1jtJY3YmiMDgTG/YEZoZjGX3qotOoNvAybYk0/87C54y++XfWegGvBsq0ufbkonDdB7mcw6iDSwrbZQVbsM40W3LuArvr/+vkw3zip7HsghcKwGJOyjfHbMT3BbByeIvGdzmRdhsBrd5wbqDW1Q5/6+Cm+QOgYFxUby7YfS57hRzg54Hd6DktGMxY6DcLs4XGNCf2xF/2ugP28azbh9z8mnjbJ9tGdungfkSWpaDv1eba7/heOJs50ZZdptH5yXDxRbsHtFPl0yzXawtYuzjnPFspCOXnBnHddjIeJl4lCP+YxwnIWOfCbPxX1+L+Hh247dXO3OO3+0Zv2zZtJnzNs8OzDZzz0+6TXawMD+NH4C39HZkbOvxDt7SY7S/xy29neLdaX9LL8sydSPtFOcvd2fGicKW3TvH2dvI6i096T69QxV4Z4x/8tgl3j/tky3nro5w7uYI5+6MnGr+7JwscMLQfUq3l/bF7nT2CPgXkBMZFxV7MC4qqD/owVX+2vpFOrsj3MNC/+Vm3MqRMbYnI6fl/mStrfZ0oD/tZak/Sf6yvLfwL8u21jv7OBI7lrgzF1kbl0sciB1LB2DsWMYcO9bWNtly7svH2ezqGNrXgTG0fACOoRWOjKH9+DhbXB1D+zkwhvYfgGPoAMYx1F8X7hv4yupx4f4r8e60v3CfZZkN4FDucg8UfpFZ232ghQv3/bVdtyGwEwS5OYc6wlkT8AcrrYsgvVL1ta8qWaXkICUHKzlEyaFKDlOyWskaJYcr+Rrpl6Wg9TZdM9gVBr23/BYGPYOhPlzZyqsvrhcQOwLDXtyWnMdb7zJdV27Q8zCDeCbCn5q1FtLLVx2yZvma5YvWLF15wLKFa1YtW33AQavmL1m5knYGrAQ7RSLCSDM/hzgkH9K5JA8/l0+0tf3QBzIvQ/ojUq6ytFwMeDmbLZbd48cIR8DJkSTT/9KKp8x++aWVbsBPg+4fEBwZ710p94amVQzLueWws/AIxqXhkYyDu78C0kE+IPUISEfBydd9QHIzIB1lBKSv90NAOogxIB3FGJC+7mBAOtgHpB4B6RtwcrQPSG4GpG8YAenofghIBzMGpG8wBqSjHQxIq31A6hGQvgknx/iA5GZA+qYRkI7ph4C0mjEgfZMxIB3jYEBa4wNSj4D0LTg51gckNwPSt4yAdGw/BKQ1jAHpW4wB6VgHA9LhPiD1CEjfhpPjfEByMyB92whIx/VDQDqcMSB9mzEgHWdpcLM/RSLgs3klo/++wxzQe3X+gD+gczJT3u+SgOg3S2VZpm6k78b5y/0eY+e3Zff34uxtZHX3JecGtOPjsvulbpvj4/zbPSY68rgNzrY+gbGtJzr4uA1G+3tMRCf6iYi3kU60MBGdJHwi0nafZHkiku7TgHRkTk66Uzdbzq8y2nyyg6v5ky0F0VN8EOVtpFMsBNFThQdRbfepA3g1f5rw1bxum9MsrOYnD8DV/OmMbT3ZwdU8o/09JqIz/ETE20hnWJiIzhQ+EWm7z3RsNc/t04B0ZE5O+nu2bDm/xmjzWQ6u5s+yFETP9kGUt5HOthBEzxEeRLXd5wzg1fz3ha/mddt838JqPj0AV/PnMrZ12sHVPKP9PSai8/xExNtI51mYiM4XPhFpu893bDXP7VM8uCfMYxg5L4jbGbySFwkXCl8k6Da50MIioXkALhIuYmzrZgcXCYz291gkXOwXCbyNdLGFRcIlwhcJ2u5LHFskcPsUD+4J81hGzksH4CLhMuGLBN0ml1lYJLQOwEXC5Yxt3ergIoHR/h6LhCv8IoG3ka6wsEi4UvgiQdt9pWOLBG6f4sE9YR7HyHnVAFwkXC18kaDb5GoLi4SpA3CR8APGtp7q4CKB0f4ei4Rr/CKBt5GusbBIuFb4IkHbfa1jiwRunwakI1PObMuOM9p8CKPN1zEGpP4KotdZCqI/9EGUt5F+aCGIXi88iGq7r7ccRCWv5m8QvprXbXODhdV8xwBczf+Isa07HFzNM9rfYyL6sZ+IeBvpxxYmohuFT0Ta7hsdW81z+zQgHZlyZlt2A6PNhzLafJODq/mbLAXRm30Q5W2kmy0E0Z8ID6La7p8M4NX8LcJX87ptbrGwmp8+AFfzP2Vs6+kOruYZ7e8xEd3qJyLeRrrVwkT0M+ETkbb7Z46t5jl9qtn0AMEBpB+H81nQ9Z+6tP466KNBJ5XcptI/h75C/8nhIfCeQ0EfBvoY0MeCPg50uZLbVfoXdNQG/JPOHfH+addsOX/pCOedzAFd9x8M1ndA3/gl6DtB6ycT36XSd1vuK/c40gb3OsJ5n8W+cg/0jXtB30f6yv0q/YDlvvKgI23wkCOcD1vsKw9C33gI9MOkrzyi0o9a7iuPOdIGjzvC+YTFvvIY9I3HQT9B+sqTKv2U5b7ytCNt8CtHOJ+x2Feehr7xK9DPkL7yrEo/Z7mvPO9IG7zgCOeLFvvK89A3XgD9IukrL6n0ry33lZcdaYNXHOF81WJfeRn6xiugXyV95Tcq/VvLfeV3jrTB7x3h/IPFvvI76Bu/B/0H0lf+qNJ/stxX/uxIG/zFQhuga/8MPv8L6AIlf1Xpv1n2/d8d8f1rFn3/d/D5a8T3/1Dpf1r2/b8c8f2/Lfr+X+DzfxPfv67S/7Hs+zcc8f2bFn3/Bvj8TeL7t1T6v5Z9/7Yjvn/Hou/fBp+/Q3z/rkq/Z9n37zvi+w8s+v598PkHxPcfqvT/LPv+I0d8/7FF338EPv+Y+P4Tlf7Usu8/c8T3n1v0/Wfg88+J7/WXgFjCru/jCTd8n3CEM8cRzlxHOPMc4cx3hLPAEc5CRziTjnCmHOEscoSz2BHOEkc4Sx3hLHOEs9wRzgpHOCsd4axyhHOQI5zVjnAOdoSzhpETv0M3QXm3w3fnr4HW3221ToDOAZ0L+i543/2gHwH9JOhnQb8E+jeg/wj6r6D/Afp10G+Bfhf0h6A/AR1A/Xmg80EXgC4EnQSdAl0Euhh0CehS0GWgy0FXgK4EXQV6EOhq0INB14CeoKRWpesS3fvA8TLESrDhNtC1WJeSISo91LheEWfuP5w/3hnG1xfD/vrBTWPAO37wqCft5n9wk2WZjeBQ7nKHJ/g6vy27hyfY26jz12yJoPcheXDZ5BzmCGdtwB+stC6CdIPqFI1KRigZqWSUktFKxigZq2SckiYl45VMIB2oFLTeRGMGu0LS12Ikz7gH8sUPoxj9lbYQXPX/l+q6mQB2BIa9JUHPH3ox1btM15Ub9DzMIJ6J8KdmrYX08lWHrFm+ZvmiNUtXHrBs4ZpVy1YfcNCq+UtWrqSdASvBTpGIMNLMzyEOyYd0LsnDz+UTHTOtyIDONhIPZ16G9EekHGHp60bAy9lsseyQdq6J4PRJxPk42uJBd4fKI+2Bb9Wd8fOgd1vFSDoO70n08Z7YWsqhox4/j6Oe2SdWIpjV5V8MnKsb8FOoSJ9PSvSulPtBBCMYlnPLV3QdExmXhpMYB3d/BaSRPiD1CEiTwelTfEByMyBNNgLSlH4ISCMZA9JkxoA0xcGANMoHpB4BKQ1OD31AcjMgpY2AFPZDQBrFGJDSjAEpdDAgjfMBqUdAagant/iA5GZAajYCUks/BKRxjAGpmTEgtTgYkJp8QOoRkFrB6W0+ILkZkFqNgNTWDwGpiTEgtTIGpDYHA9J4H5B6BKSp4PR2H5DcDEhTjYDU3g8BaTxjQJrKGJDaLQ1ubv81Bnw2NzD6r4M5oPfq/AF/QOdkprzT/GYp3kaaZmGz1HThm6W03dMtbJYKyBE3yubcqpBtWTMSsvulbpsZCf7tHjMdeUw+Z1vPZGzrmQ4+Jn+mpYlolp+IeBtploWJaLbwiUjbPdvyRCTdpwHpyJycdKdutpyNjDbPcXA1P8dSEM34IMrcSBaC6FzhQVTbPXcAr+bnCV/N67aZZ2E1P3sArubnM7b1bAdX8/MtTUQL/ETE20gLLExEmwifiLTdmzi2mt/EkdU8/T1btpwTGG1e6OBqfqGlILqpD6K8jbSphSC6mfAgqu3ebACv5jcXvprXbbO5hdV8ZgCu5rdgbOuMg6v5LSxNRFv6iYi3kba0MBFtJXwi0nZv5dhqfitLq3nuCbOFkXPrhJ3BK3mRsI3wRYJuk20sLBLmDcBFwraMbT3PwUXCtpYWCYv8IoG3kRZZWCQsFr5I0HYvdmyRsNiRRUIbI+d2A3CRsL3wRYJuk+0tLBIWDMBFwg6Mbb3AwUXCDpYWCTv6RQJvI+1oYZGwk/BFgrZ7J8cWCTs5skhoZ+TceQAuEnYRvkjQbbKLhUXCwgG4SNiVsa0XOrhI2NXSImE3v0jgbaTdLCwSdhe+SNB27+7YImF3S4sEM4hm/Z8WGW0ezWjzHg5uHtrDUhDd0wdR3kba00IQ3Ut4ENV27zWANw/tLXw1r9tmbwur+c0G4Gp+H8a23szB1fw+liaiJX4i4m2kJRYmoqXCJyJt91LHVvNLHVnNNzLaPIbR5mUOruaXWQqi+/ogyttI+1oIosuFB1Ft9/IBvJpfIXw1r9tmhYXV/BYDcDW/H2Nbb+Hgan4/SxPR/n4i4m2k/S1MRAcIn4i03Qc4tprn9Klm0wMEB5B+HI7+z8OTQE8BHYJOKvmKSh8IfYX+k8PR8J4xoMeCbgHdBroddLmSlSr91UQQ9OWvbG1cleifds2W8yBHOA9mDuj0P2Gvgr5xEOiDQesnEx+i0oda7iuHOdIGqx3hXGOxrxwGfWM16DWkrxyu0l+z3FeOcKQNjnSE8yiLfeUI6BtHgj6K9JWvq/Q3LPeVox1pg286wnmMxb5yNPSNb4I+hvSVb6n0sZb7yrcdaYPjHOH8jsW+8m3oG8eB/g7pK99V6e9Z7ivHO9IGJzjCeaLFvnI89I0TQJ9I+spJKn2y5b5yiiNtcKojnKdZ7CunQN84FfRppK+crtJnWO4rZzrSBmc5wnm2xb5yJvSNs0CfTfrKOSr9fct95VxH2uA8C22AF5zPBZ+fB7pAyfkqfYFl31/oiO8vsuj7C8HnFxHfX6zSl1j2/aWO+P4yi76/FHx+GfH95Sp9hWXfX+mI76+y6PsrwedXEd9frdI/sOz7axzx/bUWfX8N+Pxa4vvrVPqHln1/vSO+v8Gi768Hn99AfP8jlf6xZd/f6Ijvb7Lo+xvB5zcR39+s0j+x7PtbHPH9Ty36/hbw+U+J729V6Z9Z9v1tjvj+545w3u4I5y8c4bzDEc5fOsJ5pyOcdznCebcjnPc4wnmvI5z3OcJ5vyOcDzjC+aAjnA85wvmwI5yPOML5qCOcjznC+bgjnE84wvmkhe/QTVDeSvjuPAH0baB/Dvp20L8AfQjow0F/HfS3QH8X9EmgTwd9DujzQV8M+nLQV4O+DvSPQN8M+lbQd4D+Jeg7Qd8F+m7Q94C+F/R9oO8H/QDoB0E/BPph0I+AfhT0Y6AfB/0E6CfRf0qeUumnE937wPEyRAO85yugnwJdoeRXKv1Mouu9xmULK33pwDhbXwojcL9s2aGZwVh2r7ripMxnwenPEecXgo4H3dea8kh74Fv1bwQ+D3q3VYyk4/CeRB/via2lnEKSh58vISyMPklb+FFQ2uqPfmLgXN2Ad0NF+vw5EixN52E+5yDawLLSRlnhswk+ruf4JopwfQNSOrsjzIZ5Rc9jWQSulYDEHZSHJ+wEt+ehAV/4ksFtXoTNZnCbF6w7uEWV8/8quEnuEBgYn090N4w+151ibtDz4A6UnHa8wBgoX0zwBQb054vEnzb6w3OJrNvHnHzaONvnOcb22Yr5Z/FZDv5eba79huOJs523lmW3eXQ+BuAFC3Zv00+PQch2sfY8Yx/njGfbOvIYCcZxHW7N+OiHRY74j3GchIx9JszGf30t4uPZjd9e7cw5fl9inDtt2sz56JZfM9vMPT/pNvm1hflppwH4mJ6XGdt6Jwcf08Nof4/H9LxCvoz7x/RkWaZupFcS/OW+yjiQbNn9aoK9jaw+pke6T4covmEWJo/fOHKb8beOcP7OEc7fM3Kq+TPQghOG7lO6vbQvfm9cpudeQGZxt6NXWX9gXFTkgE/Mg6v8tfWLdHZH+AcL/Zeb8VeOjLE/MnJa7k/W2uqPDvSnP1nqT5K/LP9Z+JdlW+udvzgSO/7qzlxkbVz+1YHY8bcBGDv+buniIvcYeo2Ps9nVMfSaA2PoHwNwDP3TkTH0Lz7OFlfH0L8cGEP/HoBj6HVHxtB/HFlzvuEI55uOcL7FzMl+Q1KV8RsLdu8ifKPQ31QZr1mwe1eZG4V6cf6XMW4ytnVoy3/c7fy2I/HnHUc433WE8z1HON93hPMDRzg/dITzf45wfuQI58eOcH7iCOenjnB+5gjn545w6o0BnJzc3wfuVgXuE+e3ew/h34P2UjbvbcHuPR35HhTj65chY1uHewrvN0tVn1lmod/EhceJ5crmFRbsTgi3e39l8wEW7M4Rbre+Vv0XC3sQ9hE+vvV+mD9bsHuJI/NCLuO8wNjW4RLp11VVQ/zdQr/JEx4n9P3rf1qwO1+43fqe4+sW7C7IsRMnuDkLHeFMOsKZcoSzyBHOYkc4SxzhLHWEs8wSZ9zgTGd3dD78hcvmckdsjjPaXOGIzYmAz+ZKR2zOYbS5yhGbcxltHuSIzXmMNlc7YvOJjDYPdsTm/zDuW6xxxOY3GG2udcTmNxltrnPE5rcYbR7iiM3/ZbR5qCM2v81o8zBHbH6H0eZ6R2x+l9Hm4Y7Y/B6jzQ2O2Pw+o82Njtj8AaPNIxyx+UNGm0c6YvP/GG0e5YjNHzHaPNoRmz9mtHmMIzZ/wmjzWEds/pTR5nGO2PwZo81Njtj8OaPN4x2xme5vzdbmCa7cu2G0eaIr924YbZ7kyr0bRpsnu3LvhtHmKa7cu2G0Oe3KvRtGm0NHbM5ntLnZEZsLGG1uccTmQkabWx2xOcloc5sjNqcYbZ7qiM1FjDa3O2JzMaPNHY7YXMJo8zRHbC5ltHm6IzaXMdo8w5V1WMBn80xX1mGMNs9yZR3GaPNsV9ZhjDbPcWUdxmhzxpV1GKPNc11ZhzHaPM+VdRijzfNdWYcx2rzAlXUYo82bOGJzOaPNCx2xuYLR5k0dsbmS0ebNHLG5itHmzR2xeRCjzVtYsHkpaPzH3Pq3UfhcbP1bEv29UH9P0t8b9Dparyv1OkuvO/Q8rOclHad13NLjWPdr3c7a7molg5XUKKlVUqdkiJKhSoYpqVcyXEmDkkYlI5SMVDJKyWglY5SMVTJOSZOS8UomKJmoZJKSyUqmaF8o0Q9MbtY+VtKqpE3JVCXtSjqUTFMyXckMJTOVzFIyW8kcaJ+5SuYpma9kgZJNlCxUsqmSzZRsrmQLJVsq2UrJ1kq2UbKtkkVKFivZTsn2SnZQsqOSnZTsrGQXJbsq2U3J7kr2ULKnkr2U7K1kHyVLoC2mQ3vo3w/q39Pp35fp31vp3x/p3+Po36fo32vo3y/o/fx6f7ve7633P+v9wHp/rN4vqvdP6v2Een+d3m+m91/p/Uh6f47er6L3b+j9DPr+vr7fre//6vuh+v6gvl+m7x/p+yn6/oK+3q6vP+vrsfr6pL5ep69f6es5+vqG/r6vv//q74Od34+U6PWzXk/q9ZVeb+j5V89HOj7reKXHr+7P/wefsByI4jcHAA==", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/aztec.js/src/abis/schnorr_account_contract.json b/yarn-project/aztec.js/src/abis/schnorr_account_contract.json index 3c4ff949cd6..d90bd6cfc02 100644 --- a/yarn-project/aztec.js/src/abis/schnorr_account_contract.json +++ b/yarn-project/aztec.js/src/abis/schnorr_account_contract.json @@ -140,7 +140,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json b/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json index 23c2a5e18d0..7c6243b45be 100644 --- a/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json +++ b/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json @@ -95,7 +95,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index fba6e540515..fb8cdedd015 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -5,7 +5,7 @@ import { ContractAbi } from '@aztec/foundation/abi'; import { DebugLogger } from '@aztec/foundation/log'; import { toBigInt } from '@aztec/foundation/serialize'; import { ChildContractAbi, ParentContractAbi } from '@aztec/noir-contracts/artifacts'; -import { ChildContract, ParentContract } from '@aztec/noir-contracts/types'; +import { ChildContract, ImportTestContract, ParentContract, TestContract } from '@aztec/noir-contracts/types'; import { AztecRPC, TxStatus } from '@aztec/types'; import { setup } from './fixtures/utils.js'; @@ -17,14 +17,8 @@ describe('e2e_nested_contract', () => { let accounts: AztecAddress[]; let logger: DebugLogger; - let parentContract: ParentContract; - let childContract: ChildContract; - beforeEach(async () => { ({ aztecNode, aztecRpcServer, accounts, wallet, logger } = await setup()); - - parentContract = (await deployContract(ParentContractAbi)) as ParentContract; - childContract = (await deployContract(ChildContractAbi)) as ChildContract; }, 100_000); afterEach(async () => { @@ -34,129 +28,166 @@ describe('e2e_nested_contract', () => { } }); - const deployContract = async (abi: ContractAbi) => { - logger(`Deploying L2 contract ${abi.name}...`); - const deployer = new ContractDeployer(abi, aztecRpcServer); - const tx = deployer.deploy().send(); - - await tx.isMined({ interval: 0.1 }); - - const receipt = await tx.getReceipt(); - const contract = await Contract.create(receipt.contractAddress!, abi, wallet); - logger(`L2 contract ${abi.name} deployed at ${contract.address}`); - return contract; - }; - - const addressToField = (address: AztecAddress): bigint => Fr.fromBuffer(address.toBuffer()).value; - - const getChildStoredValue = (child: { address: AztecAddress }) => - aztecRpcServer.getPublicStorageAt(child.address, new Fr(1)).then(x => toBigInt(x!)); - - /** - * Milestone 3. - */ - it('performs nested calls', async () => { - const tx = parentContract.methods - .entryPoint(childContract.address, Fr.fromBuffer(childContract.methods.value.selector)) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - - expect(receipt.status).toBe(TxStatus.MINED); - }, 100_000); - - it('performs public nested calls', async () => { - const tx = parentContract.methods - .pubEntryPoint(childContract.address, Fr.fromBuffer(childContract.methods.pubValue.selector), 42n) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - - expect(receipt.status).toBe(TxStatus.MINED); - }, 100_000); - - it('enqueues a single public call', async () => { - const tx = parentContract.methods - .enqueueCallToChild(childContract.address, Fr.fromBuffer(childContract.methods.pubStoreValue.selector), 42n) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - expect(receipt.status).toBe(TxStatus.MINED); - - expect(await getChildStoredValue(childContract)).toEqual(42n); - }, 100_000); - - // Fails with "solver opcode resolution error: cannot solve opcode: expression has too many unknowns %EXPR [ 0 ]%" - // See https://github.com/noir-lang/noir/issues/1347 - it.skip('enqueues multiple public calls', async () => { - const tx = parentContract.methods - .enqueueCallToChildTwice( - addressToField(childContract.address), - Fr.fromBuffer(childContract.methods.pubStoreValue.selector).value, - 42n, - ) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - expect(receipt.status).toBe(TxStatus.MINED); - - expect(await getChildStoredValue(childContract)).toEqual(85n); - }, 100_000); - - it('enqueues a public call with nested public calls', async () => { - const tx = parentContract.methods - .enqueueCallToPubEntryPoint( - childContract.address, - Fr.fromBuffer(childContract.methods.pubStoreValue.selector), - 42n, - ) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - expect(receipt.status).toBe(TxStatus.MINED); - - expect(await getChildStoredValue(childContract)).toEqual(42n); - }, 100_000); - - // Fails with "solver opcode resolution error: cannot solve opcode: expression has too many unknowns %EXPR [ 0 ]%" - // See https://github.com/noir-lang/noir/issues/1347 - it.skip('enqueues multiple public calls with nested public calls', async () => { - const tx = parentContract.methods - .enqueueCallsToPubEntryPoint( - childContract.address, - Fr.fromBuffer(childContract.methods.pubStoreValue.selector), - 42n, - ) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - expect(receipt.status).toBe(TxStatus.MINED); - - expect(await getChildStoredValue(childContract)).toEqual(84n); - }, 100_000); + describe('parent manually calls child', () => { + let parentContract: ParentContract; + let childContract: ChildContract; + + beforeEach(async () => { + parentContract = (await deployContract(ParentContractAbi)) as ParentContract; + childContract = (await deployContract(ChildContractAbi)) as ChildContract; + }, 100_000); + + const deployContract = async (abi: ContractAbi) => { + logger(`Deploying L2 contract ${abi.name}...`); + const deployer = new ContractDeployer(abi, aztecRpcServer); + const tx = deployer.deploy().send(); + + await tx.isMined({ interval: 0.1 }); + + const receipt = await tx.getReceipt(); + const contract = await Contract.create(receipt.contractAddress!, abi, wallet); + logger(`L2 contract ${abi.name} deployed at ${contract.address}`); + return contract; + }; + + const addressToField = (address: AztecAddress): bigint => Fr.fromBuffer(address.toBuffer()).value; + + const getChildStoredValue = (child: { address: AztecAddress }) => + aztecRpcServer.getPublicStorageAt(child.address, new Fr(1)).then(x => toBigInt(x!)); + + /** + * Milestone 3. + */ + it('performs nested calls', async () => { + const tx = parentContract.methods + .entryPoint(childContract.address, Fr.fromBuffer(childContract.methods.value.selector)) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + + expect(receipt.status).toBe(TxStatus.MINED); + }, 100_000); + + it('performs public nested calls', async () => { + const tx = parentContract.methods + .pubEntryPoint(childContract.address, Fr.fromBuffer(childContract.methods.pubValue.selector), 42n) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + + expect(receipt.status).toBe(TxStatus.MINED); + }, 100_000); + + it('enqueues a single public call', async () => { + const tx = parentContract.methods + .enqueueCallToChild(childContract.address, Fr.fromBuffer(childContract.methods.pubStoreValue.selector), 42n) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + expect(receipt.status).toBe(TxStatus.MINED); + + expect(await getChildStoredValue(childContract)).toEqual(42n); + }, 100_000); + + // Fails with "solver opcode resolution error: cannot solve opcode: expression has too many unknowns %EXPR [ 0 ]%" + // See https://github.com/noir-lang/noir/issues/1347 + it.skip('enqueues multiple public calls', async () => { + const tx = parentContract.methods + .enqueueCallToChildTwice( + addressToField(childContract.address), + Fr.fromBuffer(childContract.methods.pubStoreValue.selector).value, + 42n, + ) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + expect(receipt.status).toBe(TxStatus.MINED); + + expect(await getChildStoredValue(childContract)).toEqual(85n); + }, 100_000); + + it('enqueues a public call with nested public calls', async () => { + const tx = parentContract.methods + .enqueueCallToPubEntryPoint( + childContract.address, + Fr.fromBuffer(childContract.methods.pubStoreValue.selector), + 42n, + ) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + expect(receipt.status).toBe(TxStatus.MINED); + + expect(await getChildStoredValue(childContract)).toEqual(42n); + }, 100_000); + + // Fails with "solver opcode resolution error: cannot solve opcode: expression has too many unknowns %EXPR [ 0 ]%" + // See https://github.com/noir-lang/noir/issues/1347 + it.skip('enqueues multiple public calls with nested public calls', async () => { + const tx = parentContract.methods + .enqueueCallsToPubEntryPoint( + childContract.address, + Fr.fromBuffer(childContract.methods.pubStoreValue.selector), + 42n, + ) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + expect(receipt.status).toBe(TxStatus.MINED); + + expect(await getChildStoredValue(childContract)).toEqual(84n); + }, 100_000); + + // Regression for https://github.com/AztecProtocol/aztec-packages/issues/640 + // Fails with "solver opcode resolution error: cannot solve opcode: expression has too many unknowns %EXPR [ 0 ]%" + // See https://github.com/noir-lang/noir/issues/1347 + it.skip('reads fresh value after write within the same tx', async () => { + const tx = parentContract.methods + .pubEntryPointTwice( + addressToField(childContract.address), + Fr.fromBuffer(childContract.methods.pubStoreValue.selector).value, + 42n, + ) + .send({ origin: accounts[0] }); + + await tx.isMined({ interval: 0.1 }); + const receipt = await tx.getReceipt(); + + expect(receipt.status).toBe(TxStatus.MINED); + expect(await getChildStoredValue(childContract)).toEqual(85n); + }, 100_000); + }); - // Regression for https://github.com/AztecProtocol/aztec-packages/issues/640 - // Fails with "solver opcode resolution error: cannot solve opcode: expression has too many unknowns %EXPR [ 0 ]%" - // See https://github.com/noir-lang/noir/issues/1347 - it.skip('reads fresh value after write within the same tx', async () => { - const tx = parentContract.methods - .pubEntryPointTwice( - addressToField(childContract.address), - Fr.fromBuffer(childContract.methods.pubStoreValue.selector).value, - 42n, - ) - .send({ origin: accounts[0] }); - - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); - - expect(receipt.status).toBe(TxStatus.MINED); - expect(await getChildStoredValue(childContract)).toEqual(85n); - }, 100_000); + describe('importer uses autogenerated test contract interface', () => { + let importerContract: ImportTestContract; + let testContract: TestContract; + + beforeEach(async () => { + logger(`Deploying importer test contract`); + importerContract = await ImportTestContract.deploy(wallet).send().deployed(); + logger(`Deploying test contract`); + testContract = await TestContract.deploy(wallet).send().deployed(); + }, 30_000); + + it('calls a method with multiple arguments', async () => { + logger(`Calling main on importer contract`); + await importerContract.methods.main(testContract.address).send().wait(); + }, 30_000); + + it('calls a method no arguments', async () => { + logger(`Calling noargs on importer contract`); + await importerContract.methods.callNoArgs(testContract.address).send().wait(); + }, 30_000); + + it('calls an open function', async () => { + logger(`Calling openfn on importer contract`); + await importerContract.methods.callOpenFn(testContract.address).send().wait(); + }, 30_000); + }); }); diff --git a/yarn-project/foundation/src/abi/abi_coder.ts b/yarn-project/foundation/src/abi/abi_coder.ts index c33e3db4cd9..5fd4ccd48fa 100644 --- a/yarn-project/foundation/src/abi/abi_coder.ts +++ b/yarn-project/foundation/src/abi/abi_coder.ts @@ -34,7 +34,7 @@ export function computeFunctionSelector(signature: string, size: number) { */ export function generateFunctionSelector(name: string, parameters: ABIParameter[]) { const signature = computeFunctionSignature(name, parameters); - return keccak(Buffer.from(signature)).slice(0, 4); + return computeFunctionSelector(signature, 4); } /** diff --git a/yarn-project/noir-compiler/package.json b/yarn-project/noir-compiler/package.json index 93c3b9a6e86..24c5ace3f5f 100644 --- a/yarn-project/noir-compiler/package.json +++ b/yarn-project/noir-compiler/package.json @@ -40,7 +40,11 @@ "@noir-lang/noir_wasm": "0.5.1-9740f54", "commander": "^9.0.0", "fs-extra": "^11.1.1", + "lodash.camelcase": "^4.3.0", + "lodash.capitalize": "^4.2.1", "lodash.compact": "^3.0.1", + "lodash.times": "^4.3.2", + "lodash.upperfirst": "^4.3.1", "toml": "^3.0.0", "tslib": "^2.4.0" }, @@ -49,7 +53,11 @@ "@rushstack/eslint-patch": "^1.1.4", "@types/fs-extra": "^11.0.1", "@types/jest": "^29.5.0", + "@types/lodash.camelcase": "^4.3.7", + "@types/lodash.capitalize": "^4.2.7", "@types/lodash.compact": "^3.0.7", + "@types/lodash.times": "^4.3.7", + "@types/lodash.upperfirst": "^4.3.7", "@types/node": "^18.7.23", "jest": "^29.5.0", "ts-jest": "^29.1.0", diff --git a/yarn-project/noir-compiler/src/cli.ts b/yarn-project/noir-compiler/src/cli.ts index d35fff1cc0c..f335b8bdebb 100644 --- a/yarn-project/noir-compiler/src/cli.ts +++ b/yarn-project/noir-compiler/src/cli.ts @@ -7,7 +7,7 @@ import fs from 'fs/promises'; import nodePath from 'path'; import { ContractCompiler } from './compile.js'; -import { generateType } from './index.js'; +import { generateTSContractInterface } from './index.js'; const program = new Command(); const log = createConsoleLogger('noir-compiler-cli'); @@ -39,7 +39,7 @@ const main = async () => { .argument('[targetPath]', 'Path to the output file') .action(async (buildPath: string, targetPath: string) => { const artifact = readJSONSync(buildPath); - const output = generateType(artifact); + const output = generateTSContractInterface(artifact); await fs.writeFile(targetPath, output); log(`Written type for ${artifact.name} to ${targetPath}`); }); diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts b/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts new file mode 100644 index 00000000000..2e38b9fea2c --- /dev/null +++ b/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts @@ -0,0 +1,261 @@ +import { + ABIParameter, + ABIVariable, + ContractAbi, + FunctionAbi, + FunctionType, + StructType, + generateFunctionSelector, +} from '@aztec/foundation/abi'; + +import camelCase from 'lodash.camelcase'; +import compact from 'lodash.compact'; +import times from 'lodash.times'; +import upperFirst from 'lodash.upperfirst'; + +/** + * Returns whether this function type corresponds to a private call. + * @param functionType - The function type. + * @returns Whether this function type corresponds to a private call. + */ +function isPrivateCall(functionType: FunctionType) { + return functionType === FunctionType.SECRET; +} + +/** + * Generates a call to a private function using the context. + * @param selector - The selector of a function. + * @param functionType - Type of the function. + * @returns A code string. + */ +function generateCallStatement(selector: string, functionType: FunctionType) { + const callMethod = isPrivateCall(functionType) ? 'call_private_function' : 'call_public_function'; + return ` + context.${callMethod}(self.address, ${selector}, serialised_args)`; +} + +/** + * Formats a string as pascal case. + * @param str - A string. + * @returns A capitalised camelcase string. + */ +function toPascalCase(str: string) { + return upperFirst(camelCase(str)); +} + +/** + * Returns a struct name given a list of fragments. + * @param fragments - Fragments. + * @returns The concatenation of the capitalised fragments. + */ +function getStructName(...fragments: string[]) { + return fragments.map(toPascalCase).join('') + 'Struct'; +} + +/** + * Returns a Noir type name for the given ABI variable. + * @param param - ABI variable to translate to a Noir type name. + * @param parentNames - Function name or parent structs or arrays to use for struct qualified names. + * @returns A valid Noir basic type name or a name for a struct. + */ +function getTypeName(param: ABIVariable, ...parentNames: string[]): string { + const type = param.type; + switch (type.kind) { + case 'field': + return 'Field'; + case 'boolean': + return 'bool'; + case 'integer': + return `${type.sign === 'signed' ? 'i' : 'u'}${type.width}`; + case 'string': + throw new Error(`Strings not supported yet`); + case 'array': + return `[${getTypeName({ name: param.name, type: type.type }, ...parentNames)};${type.length}]`; + case 'struct': + return getStructName(param.name, ...parentNames); + default: + throw new Error(`Unknown type ${type}`); + } +} + +/** + * Generates a parameter string. + * @param param - ABI parameter. + * @param functionData - Parent function. + * @returns A Noir string with the param name and type to be used in a function call. + */ +function generateParameter(param: ABIParameter, functionData: FunctionAbi) { + const typename = getTypeName(param, functionData.name); + return `${param.name}: ${typename}`; +} + +/** + * Collects all parameters for a given function and flattens them according to how they should be serialised. + * @param parameters - Paramters for a function. + * @returns List of parameters flattened to basic data types. + */ +function collectParametersForSerialisation(parameters: ABIVariable[]) { + const flattened: string[] = []; + for (const parameter of parameters) { + const { name } = parameter; + if (parameter.type.kind === 'array') { + const nestedType = parameter.type.type; + const nested = times(parameter.type.length, i => + collectParametersForSerialisation([{ name: `${name}[${i}]`, type: nestedType }]), + ); + flattened.push(...nested.flat()); + } else if (parameter.type.kind === 'struct') { + const nested = parameter.type.fields.map(field => + collectParametersForSerialisation([{ name: `${name}.${field.name}`, type: field.type }]), + ); + flattened.push(...nested.flat()); + } else if (parameter.type.kind === 'string') { + throw new Error(`String not yet supported`); + } else if (parameter.type.kind === 'field') { + flattened.push(name); + } else { + flattened.push(`${name} as Field`); + } + } + return flattened; +} + +/** + * Generates Noir code for serialising the parameters into an array of fields. + * @param parameters - Parameters to serialise. + * @returns The serialisation code. + */ +function generateSerialisation(parameters: ABIParameter[]) { + const flattened = collectParametersForSerialisation(parameters); + const declaration = ` let mut serialised_args = [0; ${flattened.length}];`; + const lines = flattened.map((param, i) => ` serialised_args[${i}] = ${param};`); + return [declaration, ...lines].join('\n'); +} + +/** + * Generate a function interface for a particular function of the Noir Contract being processed. This function will be a method of the ContractInterface struct being created here. + * @param functionData - data relating to the function, which can be used to generate a callable Noir Function. + * @returns a code string. + */ +function generateFunctionInterface(functionData: FunctionAbi) { + const { name, parameters } = functionData; + const selector = '0x' + generateFunctionSelector(name, parameters).toString('hex'); + const serialisation = generateSerialisation(parameters); + const callStatement = generateCallStatement(selector, functionData.functionType); + const allParams = ['self', 'context: &mut Context', ...parameters.map(p => generateParameter(p, functionData))]; + const retType = isPrivateCall(functionData.functionType) ? `-> [Field; RETURN_VALUES_LENGTH] ` : ``; + + return ` + fn ${name}( + ${allParams.join(',\n ')} + ) ${retType}{ +${serialisation} +${callStatement} + } + `; +} + +/** + * Generates static impots. + * @returns A string of code which will be needed in every contract interface, regardless of the contract. + */ +function generateStaticImports() { + return `use dep::std; +use dep::aztec::context::Context; +use dep::aztec::constants_gen::RETURN_VALUES_LENGTH;`; +} + +/** + * Generate the main focus of this code generator: the contract interface struct. + * @param contractName - the name of the contract, as matches the original source file. + * @returns Code. + */ +function generateContractInterfaceStruct(contractName: string) { + return `struct ${contractName}ContractInterface { + address: Field, +} +`; +} + +/** + * Generates the implementation of the contract interface struct. + * @param contractName - The name of the contract, as matches the original source file. + * @param functions - An array of strings, where each string is valid Noir code describing the function interface of one of the contract's functions (as generated via `generateFunctionInterface` above). + * @returns Code. + */ +function generateContractInterfaceImpl(contractName: string, functions: string[]) { + return `impl ${contractName}ContractInterface { + fn at(address: Field) -> Self { + Self { + address, + } + } + ${functions.join('\n')} +} +`; +} + +/** Represents a struct along its parent names to derive a fully qualified name. */ +type StructInfo = ABIVariable & { /** Parent name */ parentNames: string[] }; + +/** + * Generates a Noir struct. + * @param struct - Struct info. + * @returns Code representing the struct. + */ +function generateStruct(struct: StructInfo) { + const fields = (struct.type as StructType).fields.map( + field => ` ${field.name}: ${getTypeName(field, struct.name, ...struct.parentNames)},`, + ); + + return ` +struct ${getStructName(struct.name, ...struct.parentNames)} { +${fields.join('\n')} +}`; +} + +/** + * Collects all structs across all parameters. + * @param params - Parameters to look for structs, either structs themselves or nested. + * @param parentNames - Parent names to derive fully qualified names when needed. + * @returns A list of struct infos. + */ +function collectStructs(params: ABIVariable[], parentNames: string[]): StructInfo[] { + const structs: StructInfo[] = []; + for (const param of params) { + if (param.type.kind === 'struct') { + const struct = { ...param, parentNames }; + structs.push(struct, ...collectStructs(param.type.fields, [param.name, ...parentNames])); + } else if (param.type.kind === 'array') { + structs.push(...collectStructs([{ name: param.name, type: param.type.type }], [...parentNames])); + } + } + return structs; +} + +/** + * Generates the Noir code to represent an interface for calling a contract. + * @param abi - The compiled Noir artifact. + * @returns The corresponding ts code. + */ +export function generateNoirContractInterface(abi: ContractAbi) { + // We don't allow calling a constructor, internal fns, or unconstrained fns from other contracts + const methods = compact( + abi.functions.filter( + f => f.name !== 'constructor' && !f.isInternal && f.functionType !== FunctionType.UNCONSTRAINED, + ), + ); + const contractStruct: string = generateContractInterfaceStruct(abi.name); + const paramStructs = methods.flatMap(m => collectStructs(m.parameters, [m.name])).map(generateStruct); + const functionInterfaces = methods.map(generateFunctionInterface); + const contractImpl: string = generateContractInterfaceImpl(abi.name, functionInterfaces); + + return `/* Autogenerated file, do not edit! */ + +${generateStaticImports()} +${paramStructs.join('\n')} + +${contractStruct} +${contractImpl} +`; +} diff --git a/yarn-project/noir-compiler/src/typegen/index.ts b/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts similarity index 97% rename from yarn-project/noir-compiler/src/typegen/index.ts rename to yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts index 74778bc00c2..d3a1ffc6606 100644 --- a/yarn-project/noir-compiler/src/typegen/index.ts +++ b/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts @@ -47,6 +47,33 @@ function generateMethod(entry: FunctionAbi) { ${entry.name}: ((${args}) => ContractFunctionInteraction) & Pick;`; } +/** + * Generates a deploy method for this contract. + * @param input - ABI of the contract. + * @returns A type-safe deploy method in ts. + */ +function generateDeploy(input: ContractAbi) { + const ctor = input.functions.find(f => f.name === 'constructor'); + const args = (ctor?.parameters ?? []).map(generateParameter).join(', '); + const abiName = `${input.name}ContractAbi`; + + return ` + /** + * Creates a tx to deploy a new instance of this contract. + */ + public static deploy(rpc: AztecRPC, ${args}) { + return new DeployMethod<${input.name}Contract>(Point.ZERO, rpc, ${abiName}, Array.from(arguments).slice(1)); + } + + /** + * Creates a tx to deploy a new instance of this contract using the specified public key to derive the address. + */ + public static deployWithPublicKey(rpc: AztecRPC, publicKey: PublicKey, ${args}) { + return new DeployMethod<${input.name}Contract>(publicKey, rpc, ${abiName}, Array.from(arguments).slice(2)); + } + `; +} + /** * Generates the constructor by supplying the ABI to the parent class so the user doesn't have to. * @param name - Name of the contract to derive the ABI name from. @@ -93,33 +120,6 @@ function generateCreate(name: string) { }`; } -/** - * Generates a deploy method for this contract. - * @param input - ABI of the contract. - * @returns A type-safe deploy method in ts. - */ -function generateDeploy(input: ContractAbi) { - const ctor = input.functions.find(f => f.name === 'constructor'); - const args = (ctor?.parameters ?? []).map(generateParameter).join(', '); - const abiName = `${input.name}ContractAbi`; - - return ` - /** - * Creates a tx to deploy a new instance of this contract. - */ - public static deploy(rpc: AztecRPC, ${args}) { - return new DeployMethod<${input.name}Contract>(Point.ZERO, rpc, ${abiName}, Array.from(arguments).slice(1)); - } - - /** - * Creates a tx to deploy a new instance of this contract using the specified public key to derive the address. - */ - public static deployWithPublicKey(rpc: AztecRPC, publicKey: PublicKey, ${args}) { - return new DeployMethod<${input.name}Contract>(publicKey, rpc, ${abiName}, Array.from(arguments).slice(2)); - } - `; -} - /** * Generates a static getter for the contract's ABI. * @param name - Name of the contract used to derive name of the ABI import. @@ -142,7 +142,8 @@ function generateAbiGetter(name: string) { * @param abiImportPath - Optional path to import the ABI (if not set, will be required in the constructor). * @returns The corresponding ts code. */ -export function generateType(input: ContractAbi, abiImportPath?: string) { +export function generateTSContractInterface(input: ContractAbi, abiImportPath?: string) { + // `compact` removes all falsey values from an array const methods = compact(input.functions.filter(f => f.name !== 'constructor').map(generateMethod)); const deploy = abiImportPath && generateDeploy(input); const ctor = abiImportPath && generateConstructor(input.name); diff --git a/yarn-project/noir-compiler/src/index.ts b/yarn-project/noir-compiler/src/index.ts index e5d5e24730a..f3dcb1fccab 100644 --- a/yarn-project/noir-compiler/src/index.ts +++ b/yarn-project/noir-compiler/src/index.ts @@ -1,2 +1,3 @@ export * from './compile.js'; -export * from './typegen/index.js'; +export * from './contract-interface-gen/typescript.js'; +export * from './contract-interface-gen/noir.js'; diff --git a/yarn-project/noir-contracts/scripts/types.sh b/yarn-project/noir-contracts/scripts/types.sh index 6ba44fc1b02..c99b99e8f92 100755 --- a/yarn-project/noir-contracts/scripts/types.sh +++ b/yarn-project/noir-contracts/scripts/types.sh @@ -22,7 +22,8 @@ ROOT=$(pwd) write_import() { CONTRACT_NAME=$1 - + + # Convert to PascalCase if [ "$(uname)" = "Darwin" ]; then # sed \U doesn't work on mac NAME=$(echo $CONTRACT_NAME | perl -pe 's/(^|_)(\w)/\U$2/g') @@ -35,6 +36,8 @@ write_import() { write_export() { CONTRACT_NAME=$1 + + # Convert to PascalCase if [ "$(uname)" = "Darwin" ]; then # sed \U doesn't work on mac NAME=$(echo $CONTRACT_NAME | perl -pe 's/(^|_)(\w)/\U$2/g') diff --git a/yarn-project/noir-contracts/src/contracts/child_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/child_contract/src/storage.nr index 634674859e4..5618cf75889 100644 --- a/yarn-project/noir-contracts/src/contracts/child_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/child_contract/src/storage.nr @@ -1,6 +1,6 @@ use dep::aztec::state_vars::public_state::PublicState; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FieldSerialisationMethods; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FIELD_SERIALISED_LEN; +use dep::aztec::types::type_serialisation::field_serialisation::FieldSerialisationMethods; +use dep::aztec::types::type_serialisation::field_serialisation::FIELD_SERIALISED_LEN; struct Storage { current_value: PublicState, diff --git a/yarn-project/noir-contracts/src/contracts/import_test_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/import_test_contract/Nargo.toml new file mode 100644 index 00000000000..41b131fcc79 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/import_test_contract/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "import_test_contract" +authors = [""] +compiler_version = "0.1" +type = "bin" + +[dependencies] +aztec = { path = "../../../../noir-libs/noir-aztec" } \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr new file mode 100644 index 00000000000..2eb0637b369 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr @@ -0,0 +1,84 @@ +mod test_contract_interface; + +// Contract that uses the autogenerated interface of the Test contract for calling its functions. +// Used for testing calling into other contracts via autogenerated interfaces. +contract ImportTest { + use dep::aztec::abi; + use dep::aztec::abi::PrivateContextInputs; + use dep::aztec::context::Context; + + use crate::test_contract_interface::{ + TestContractInterface, + AStructTestCodeGenStruct, + ADeepStructTestCodeGenStruct, + ANoteADeepStructTestCodeGenStruct, + ManyNotesADeepStructTestCodeGenStruct, + }; + + fn constructor( + inputs: PrivateContextInputs, + ) -> distinct pub abi::PrivateCircuitPublicInputs { + Context::new(inputs, 0).finish() + } + + // Calls the testCodeGen on the Test contract at the target address + // Used for testing calling a function with arguments of multiple types + // See yarn-project/acir-simulator/src/client/private_execution.ts + // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts + fn main( + inputs: PrivateContextInputs, + target: Field + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let mut context = Context::new(inputs, abi::hash_args([target])); + let test_contract_instance = TestContractInterface::at(target); + let return_values = test_contract_instance.testCodeGen( + &mut context, + 1, + true, + 1 as u32, + [1, 2], + AStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + ADeepStructTestCodeGenStruct { + aField: 1, + aBool: true, + aNote: ANoteADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + manyNotes: [ + ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + ] + } + ); + + context.return_values.push(return_values[0]); + context.finish() + } + + // Calls the getThisAddress on the Test contract at the target address + // Used for testing calling a function with no arguments + // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts + fn callNoArgs( + inputs: PrivateContextInputs, + target: Field + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let mut context = Context::new(inputs, abi::hash_args([target])); + let test_contract_instance = TestContractInterface::at(target); + let return_values = test_contract_instance.getThisAddress(&mut context); + context.return_values.push(return_values[0]); + context.finish() + } + + // Calls the createNullifierPublic on the Test contract at the target address + // Used for testing calling an open function + // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts + fn callOpenFn( + inputs: PrivateContextInputs, + target: Field, + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let mut context = Context::new(inputs, abi::hash_args([target])); + let test_contract_instance = TestContractInterface::at(target); + test_contract_instance.createNullifierPublic(&mut context, 1, 2); + context.finish() + } +} + diff --git a/yarn-project/noir-contracts/src/contracts/import_test_contract/src/test_contract_interface.nr b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/test_contract_interface.nr new file mode 120000 index 00000000000..412fbaacd2d --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/test_contract_interface.nr @@ -0,0 +1 @@ +../../test_contract/src/test_contract_interface.nr \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/lending_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/lending_contract/src/storage.nr index 4f247028da6..61f021e06a7 100644 --- a/yarn-project/noir-contracts/src/contracts/lending_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/lending_contract/src/storage.nr @@ -1,8 +1,8 @@ use dep::aztec::state_vars::map::Map; use dep::aztec::state_vars::public_state::PublicState; -use dep::aztec::state_vars::type_serialisation::TypeSerialisationInterface; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FieldSerialisationMethods; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FIELD_SERIALISED_LEN; +use dep::aztec::types::type_serialisation::TypeSerialisationInterface; +use dep::aztec::types::type_serialisation::field_serialisation::FieldSerialisationMethods; +use dep::aztec::types::type_serialisation::field_serialisation::FIELD_SERIALISED_LEN; use dep::std::hash::pedersen; // Utility struct used to easily get a "id" for a private user that sits in the same diff --git a/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/storage.nr index 5b5e0329dd6..b1cc0d49517 100644 --- a/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/storage.nr @@ -12,13 +12,17 @@ use dep::value_note::value_note::{ VALUE_NOTE_LEN, }; -use dep::aztec::state_vars::{ - map::Map, - set::Set, - public_state::PublicState, +use dep::aztec::{ + state_vars::{ + map::Map, + set::Set, + public_state::PublicState, + }, + types::type_serialisation::field_serialisation::{ + FIELD_SERIALISED_LEN, + FieldSerialisationMethods, + }, }; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FieldSerialisationMethods; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FIELD_SERIALISED_LEN; struct Storage { balances: Map>, diff --git a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr index b78fd50d568..9c3dca33ed7 100644 --- a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr @@ -58,7 +58,7 @@ contract Parent { targetValue, ])); - let _callStackItem = context.call_public_function(targetContract, targetSelector, [targetValue]); + context.call_public_function(targetContract, targetSelector, [targetValue]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() @@ -78,9 +78,9 @@ contract Parent { ])); // Enqueue the first public call - let return_values1 = context.call_public_function(targetContract, targetSelector, [targetValue]); + context.call_public_function(targetContract, targetSelector, [targetValue]); // Enqueue the second public call - let _return_values2 = context.call_public_function(targetContract, targetSelector, [return_values1[0]]); + context.call_public_function(targetContract, targetSelector, [targetValue]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() @@ -101,7 +101,7 @@ contract Parent { let pubEntryPointSelector = 3221316504; let thisAddress = inputs.call_context.storage_contract_address; - let _return_values = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); + context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() @@ -123,9 +123,9 @@ contract Parent { let pubEntryPointSelector = 3221316504; let thisAddress = inputs.call_context.storage_contract_address; - let _return_values1 = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); + context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); - let _return_values2 = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue + 1]); + context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue + 1]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() diff --git a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr index f5c2a4f61ce..9513325c9fa 100644 --- a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr @@ -3,13 +3,14 @@ use dep::aztec::state_vars::{ map::Map, // highlight-start:PublicState public_state::PublicState, - type_serialisation::field_serialisation::{ - FieldSerialisationMethods, - FIELD_SERIALISED_LEN, - }, // highlight-end:PublicState }; +use dep::aztec::types::type_serialisation::field_serialisation::{ + FieldSerialisationMethods, + FIELD_SERIALISED_LEN, +}; + struct Storage { // highlight-next-line:PublicState balances: Map>, diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr index db44cc275b5..33c03660f08 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr @@ -1,7 +1,8 @@ -// A contract used to test whether constructing a contract works. +// A contract used for testing a random hodgepodge of small features from simulator and end-to-end tests. contract Test { use dep::aztec::{ abi, + types::vec::BoundedVec, abi::{ PublicContextInputs, PrivateContextInputs @@ -13,7 +14,8 @@ contract Test { create_l2_to_l1_message::create_l2_to_l1_message, create_nullifier::create_nullifier, get_public_key::get_public_key, - context::get_portal_address + context::get_portal_address, + rand::rand, }; fn constructor( @@ -64,6 +66,38 @@ contract Test { context.finish() } + // Test codegen for noir interfaces + // See yarn-project/acir-simulator/src/client/private_execution.test.ts 'nested calls through autogenerated interface' + fn testCodeGen( + inputs: PrivateContextInputs, + aField: Field, + aBool: bool, + aNumber: u32, + anArray: [Field; 2], + aStruct: DummyNote, + aDeepStruct: DeepStruct, + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let mut args: BoundedVec = BoundedVec::new(0); + args.push(aField); + args.push(aBool as Field); + args.push(aNumber as Field); + args.push_array(anArray); + args.push(aStruct.amount); + args.push(aStruct.secretHash); + args.push(aDeepStruct.aField); + args.push(aDeepStruct.aBool as Field); + args.push(aDeepStruct.aNote.amount); + args.push(aDeepStruct.aNote.secretHash); + for note in aDeepStruct.manyNotes { + args.push(note.amount); + args.push(note.secretHash); + } + let args_hash = abi::hash_args(args.storage); + let mut context = Context::new(inputs, args_hash); + context.return_values.push(args_hash); + context.finish() + } + // Purely exists for testing open fn createL2ToL1MessagePublic( _inputs: PublicContextInputs, @@ -92,6 +126,13 @@ contract Test { 0 } + // Purely exists for testing + unconstrained fn getRandom( + kindaSeed: Field + ) -> Field { + kindaSeed * rand() + } + struct DummyNote { amount: Field, secretHash: Field @@ -109,4 +150,11 @@ contract Test { dep::std::hash::pedersen([self.amount, self.secretHash])[0] } } + + struct DeepStruct { + aField: Field, + aBool: bool, + aNote: DummyNote, + manyNotes: [DummyNote; 3], + } } diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr new file mode 100644 index 00000000000..32603d90544 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr @@ -0,0 +1,145 @@ +/* Autogenerated file, do not edit! */ + +use dep::std; +use dep::aztec::context::Context; +use dep::aztec::constants_gen::RETURN_VALUES_LENGTH; + +struct AStructTestCodeGenStruct { + amount: Field, + secretHash: Field, +} + +struct ADeepStructTestCodeGenStruct { + aField: Field, + aBool: bool, + aNote: ANoteADeepStructTestCodeGenStruct, + manyNotes: [ManyNotesADeepStructTestCodeGenStruct;3], +} + +struct ANoteADeepStructTestCodeGenStruct { + amount: Field, + secretHash: Field, +} + +struct ManyNotesADeepStructTestCodeGenStruct { + amount: Field, + secretHash: Field, +} + +struct TestContractInterface { + address: Field, +} + +impl TestContractInterface { + fn at(address: Field) -> Self { + Self { + address, + } + } + + fn createL2ToL1MessagePublic( + self, + context: &mut Context, + amount: Field, + secretHash: Field + ) { + let mut serialised_args = [0; 2]; + serialised_args[0] = amount; + serialised_args[1] = secretHash; + + context.call_public_function(self.address, 0x1c031d17, serialised_args) + } + + + fn createNullifierPublic( + self, + context: &mut Context, + amount: Field, + secretHash: Field + ) { + let mut serialised_args = [0; 2]; + serialised_args[0] = amount; + serialised_args[1] = secretHash; + + context.call_public_function(self.address, 0x0217ef40, serialised_args) + } + + + fn getPortalContractAddress( + self, + context: &mut Context, + aztec_address: Field + ) -> [Field; RETURN_VALUES_LENGTH] { + let mut serialised_args = [0; 1]; + serialised_args[0] = aztec_address; + + context.call_private_function(self.address, 0xe5df1726, serialised_args) + } + + + fn getPublicKey( + self, + context: &mut Context, + address: Field + ) -> [Field; RETURN_VALUES_LENGTH] { + let mut serialised_args = [0; 1]; + serialised_args[0] = address; + + context.call_private_function(self.address, 0x553aaad4, serialised_args) + } + + + fn getThisAddress( + self, + context: &mut Context + ) -> [Field; RETURN_VALUES_LENGTH] { + let mut serialised_args = [0; 0]; + + context.call_private_function(self.address, 0xd3953822, serialised_args) + } + + + fn getThisPortalAddress( + self, + context: &mut Context + ) -> [Field; RETURN_VALUES_LENGTH] { + let mut serialised_args = [0; 0]; + + context.call_private_function(self.address, 0x82cc9431, serialised_args) + } + + + fn testCodeGen( + self, + context: &mut Context, + aField: Field, + aBool: bool, + aNumber: u32, + anArray: [Field;2], + aStruct: AStructTestCodeGenStruct, + aDeepStruct: ADeepStructTestCodeGenStruct + ) -> [Field; RETURN_VALUES_LENGTH] { + let mut serialised_args = [0; 17]; + serialised_args[0] = aField; + serialised_args[1] = aBool as Field; + serialised_args[2] = aNumber as Field; + serialised_args[3] = anArray[0]; + serialised_args[4] = anArray[1]; + serialised_args[5] = aStruct.amount; + serialised_args[6] = aStruct.secretHash; + serialised_args[7] = aDeepStruct.aField; + serialised_args[8] = aDeepStruct.aBool as Field; + serialised_args[9] = aDeepStruct.aNote.amount; + serialised_args[10] = aDeepStruct.aNote.secretHash; + serialised_args[11] = aDeepStruct.manyNotes[0].amount; + serialised_args[12] = aDeepStruct.manyNotes[0].secretHash; + serialised_args[13] = aDeepStruct.manyNotes[1].amount; + serialised_args[14] = aDeepStruct.manyNotes[1].secretHash; + serialised_args[15] = aDeepStruct.manyNotes[2].amount; + serialised_args[16] = aDeepStruct.manyNotes[2].secretHash; + + context.call_private_function(self.address, 0x7c97ca29, serialised_args) + } + +} + diff --git a/yarn-project/noir-contracts/src/scripts/copy_output.ts b/yarn-project/noir-contracts/src/scripts/copy_output.ts index 7e951210ee4..3531b916e41 100644 --- a/yarn-project/noir-contracts/src/scripts/copy_output.ts +++ b/yarn-project/noir-contracts/src/scripts/copy_output.ts @@ -1,6 +1,6 @@ -import { ABIParameter, ABIType, FunctionType } from '@aztec/foundation/abi'; +import { ContractAbi, FunctionAbi, FunctionType } from '@aztec/foundation/abi'; import { createConsoleLogger } from '@aztec/foundation/log'; -import { generateType } from '@aztec/noir-compiler'; +import { generateNoirContractInterface, generateTSContractInterface } from '@aztec/noir-compiler'; import { readFileSync, writeFileSync } from 'fs'; import camelCase from 'lodash.camelcase'; @@ -11,7 +11,7 @@ import { join as pathJoin } from 'path'; import mockedKeys from './mockedKeys.json' assert { type: 'json' }; -const STATEMENT_TYPES = ['type', 'params', 'return'] as const; +// const STATEMENT_TYPES = ['type', 'params', 'return'] as const; const log = createConsoleLogger('aztec:noir-contracts'); const PROJECT_CONTRACTS = [ @@ -20,6 +20,8 @@ const PROJECT_CONTRACTS = [ { name: 'EcdsaAccount', target: '../aztec.js/src/abis/', exclude: [] }, ]; +const INTERFACE_CONTRACTS = ['test']; + /** * Writes the contract to a specific project folder, if needed. * @param abi - The Abi to write. @@ -40,27 +42,28 @@ function writeToProject(abi: any) { /** * Creates an Aztec function entry. - * @param type - The type of the function. - * @param params - The parameters of the function. + * @param type - The type of the function (secret | open | unconstrained). + * @param params - The parameters of the function ( name, type, visibility ). * @param returns - The return types of the function. * @param fn - The nargo function entry. * @returns The Aztec function entry. */ -function getFunction(type: FunctionType, params: ABIParameter[], returns: ABIType[], fn: any) { - if (!params) throw new Error(`ABI comment not found for function ${fn.name}`); +function getFunction(fn: any): FunctionAbi { + const type = fn.function_type.toLowerCase(); + const returns = fn.abi.return_type; + const isInternal = fn.is_internal; + let params = fn.abi.parameters; + // If the function is not unconstrained, the first item is inputs or CallContext which we should omit if (type !== FunctionType.UNCONSTRAINED) params = params.slice(1); - // If the function is not secret, drop any padding from the end - if (type !== FunctionType.SECRET && params.length > 0 && params[params.length - 1].name.endsWith('padding')) - params = params.slice(0, params.length - 1); return { name: fn.name, functionType: type, - isInternal: fn.is_internal, + isInternal, parameters: params, // If the function is secret, the return is the public inputs, which should be omitted - returnTypes: type === FunctionType.SECRET ? [] : returns, + returnTypes: type === FunctionType.SECRET ? [] : [returns], bytecode: fn.bytecode, // verificationKey: Buffer.from(fn.verification_key).toString('hex'), verificationKey: mockedKeys.verificationKey, @@ -69,36 +72,21 @@ function getFunction(type: FunctionType, params: ABIParameter[], returns: ABITyp /** * Creates the Aztec function entries from the source code and the nargo output. - * @param source - The source code of the contract. - * @param output - The nargo output. + * @param sourceCode - The source code of the contract. + * @param buildJson - The nargo output. * @returns The Aztec function entries. */ -function getFunctions(source: string, output: any) { - const abiComments = Array.from(source.matchAll(/\/\/\/ ABI (\w+) (params|return|type) (.+)/g)).map(match => ({ - functionName: match[1], - statementType: match[2], - value: JSON.parse(match[3]), - })); - - return output.functions +function getFunctions(_sourceCode: string, buildJson: any): FunctionAbi[] { + /** + * Sort functions alphabetically, by name. + * Remove the proving key field of the function. + * + */ + return buildJson.functions .sort((fnA: any, fnB: any) => fnA.name.localeCompare(fnB.name)) .map((fn: any) => { delete fn.proving_key; - const thisFunctionAbisComments = abiComments - .filter(abi => abi.functionName === fn.name) - .reduce( - (acc, comment) => ({ - ...acc, - [comment.statementType]: comment.value, - }), - {} as Record<(typeof STATEMENT_TYPES)[number], any>, - ); - return getFunction( - thisFunctionAbisComments.type || (fn.function_type.toLowerCase() as FunctionType), - thisFunctionAbisComments.params || fn.abi.parameters, - thisFunctionAbisComments.return || [fn.abi.return_type], - fn, - ); + return getFunction(fn); }); } @@ -106,27 +94,45 @@ const main = () => { const name = process.argv[2]; if (!name) throw new Error(`Missing argument contract name`); - const folderName = `${snakeCase(name)}_contract`; - const folderPath = `src/contracts/${folderName}`; - const source = readFileSync(`${folderPath}/src/main.nr`).toString(); - const contractName = process.argv[3] ?? upperFirst(camelCase(name)); - const build = JSON.parse(readFileSync(`${folderPath}/target/${folderName}-${contractName}.json`).toString()); - const artifacts = 'src/artifacts'; - - const abi = { - name: build.name, - functions: getFunctions(source, build), - }; + const projectName = `${snakeCase(name)}_contract`; + const projectDirPath = `src/contracts/${projectName}`; + const sourceCodeFilePath = `${projectDirPath}/src/main.nr`; + const sourceCode = readFileSync(sourceCodeFilePath).toString(); - const exampleFile = `${artifacts}/${snakeCase(name)}_contract.json`; - writeFileSync(exampleFile, JSON.stringify(abi, null, 2) + '\n'); - log(`Written ${exampleFile}`); + const contractName = upperFirst(camelCase(name)); + const buildJsonFilePath = `${projectDirPath}/target/${projectName}-${contractName}.json`; + const buildJson = JSON.parse(readFileSync(buildJsonFilePath).toString()); - writeToProject(abi); + // Remove extraneous information from the buildJson (which was output by Nargo) to hone in on the function data we actually care about: + const artifactJson: ContractAbi = { + name: buildJson.name, + functions: getFunctions(sourceCode, buildJson), + }; - const typeFile = `src/types/${name}.ts`; - writeFileSync(typeFile, generateType(abi, '../artifacts/index.js')); - log(`Written ${typeFile}`); + // Write the artifact: + const artifactsDir = 'src/artifacts'; + const artifactDestFilePath = `${artifactsDir}/${snakeCase(name)}_contract.json`; + writeFileSync(artifactDestFilePath, JSON.stringify(artifactJson, null, 2) + '\n'); + log(`Written ${artifactDestFilePath}`); + + // Write some artifacts to other packages in the monorepo: + writeToProject(artifactJson); + + // Write a .ts contract interface, for consumption by the typescript code + const tsInterfaceDestFilePath = `src/types/${name}.ts`; + writeFileSync(tsInterfaceDestFilePath, generateTSContractInterface(artifactJson, '../artifacts/index.js')); + log(`Written ${tsInterfaceDestFilePath}`); + + // Write a .nr contract interface, for consumption by other Noir Contracts + if (INTERFACE_CONTRACTS.includes(name)) { + const noirInterfaceDestFilePath = `${projectDirPath}/src/${projectName}_interface.nr`; + try { + writeFileSync(noirInterfaceDestFilePath, generateNoirContractInterface(artifactJson)); + log(`Written ${noirInterfaceDestFilePath}`); + } catch (err) { + log(`Error generating noir interface for ${name}: ${err}`); + } + } }; try { diff --git a/yarn-project/noir-libs/noir-aztec/src/abi.nr b/yarn-project/noir-libs/noir-aztec/src/abi.nr index b2a4240db29..be4fbfc8da4 100644 --- a/yarn-project/noir-libs/noir-aztec/src/abi.nr +++ b/yarn-project/noir-libs/noir-aztec/src/abi.nr @@ -358,21 +358,25 @@ global ARGS_HASH_CHUNK_LENGTH: u32 = 32; global ARGS_HASH_CHUNK_COUNT: u32 = 16; fn hash_args(args: [Field; N]) -> Field { - let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT]; - for i in 0..ARGS_HASH_CHUNK_COUNT { - let mut chunk_hash = 0; - let start_chunk_index = i * ARGS_HASH_CHUNK_LENGTH; - if start_chunk_index < (args.len() as u32) { - let mut chunk_args = [0; ARGS_HASH_CHUNK_LENGTH]; - for j in 0..ARGS_HASH_CHUNK_LENGTH { - let item_index = i * ARGS_HASH_CHUNK_LENGTH + j; - if item_index < (args.len() as u32) { - chunk_args[j] = args[item_index]; + if args.len() == 0 { + 0 + } else { + let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT]; + for i in 0..ARGS_HASH_CHUNK_COUNT { + let mut chunk_hash = 0; + let start_chunk_index = i * ARGS_HASH_CHUNK_LENGTH; + if start_chunk_index < (args.len() as u32) { + let mut chunk_args = [0; ARGS_HASH_CHUNK_LENGTH]; + for j in 0..ARGS_HASH_CHUNK_LENGTH { + let item_index = i * ARGS_HASH_CHUNK_LENGTH + j; + if item_index < (args.len() as u32) { + chunk_args[j] = args[item_index]; + } } + chunk_hash = dep::std::hash::pedersen_with_separator(chunk_args, GENERATOR_INDEX__FUNCTION_ARGS)[0]; } - chunk_hash = dep::std::hash::pedersen_with_separator(chunk_args, GENERATOR_INDEX__FUNCTION_ARGS)[0]; + chunks_hashes[i] = chunk_hash; } - chunks_hashes[i] = chunk_hash; + dep::std::hash::pedersen_with_separator(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)[0] } - dep::std::hash::pedersen_with_separator(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)[0] } diff --git a/yarn-project/noir-libs/noir-aztec/src/context.nr b/yarn-project/noir-libs/noir-aztec/src/context.nr index 36811cd88f0..8c271724b53 100644 --- a/yarn-project/noir-libs/noir-aztec/src/context.nr +++ b/yarn-project/noir-libs/noir-aztec/src/context.nr @@ -292,7 +292,7 @@ impl Context { contract_address: Field, function_selector: Field, args: [Field; ARGS_COUNT] - ) -> [Field; RETURN_VALUES_LENGTH] { + ) { let args_hash = hash_args(args); assert(args_hash == arguments::pack_arguments(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash) @@ -302,7 +302,7 @@ impl Context { &mut self, contract_address: Field, function_selector: Field, - ) -> [Field; RETURN_VALUES_LENGTH] { + ) { self.call_public_function_with_packed_args(contract_address, function_selector, 0) } @@ -311,7 +311,7 @@ impl Context { contract_address: Field, function_selector: Field, args_hash: Field - ) -> [Field; RETURN_VALUES_LENGTH] { + ) { let fields = enqueue_public_function_call_internal( contract_address, function_selector, @@ -368,7 +368,5 @@ impl Context { assert(item.public_inputs.call_context.storage_contract_address == contract_address); self.public_call_stack.push(item.hash()); - - item.public_inputs.return_values } } diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars.nr index 0148c8a5459..b35df0399d1 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars.nr @@ -1,6 +1,5 @@ mod immutable_singleton; mod map; mod public_state; -mod type_serialisation; mod set; mod singleton; \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr index b4cae24ecfa..900255b5625 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr @@ -1,6 +1,6 @@ use crate::oracle::storage::storage_read; use crate::oracle::storage::storage_write; -use crate::state_vars::type_serialisation::TypeSerialisationInterface; +use crate::types::type_serialisation::TypeSerialisationInterface; struct PublicState { storage_slot: Field, diff --git a/yarn-project/noir-libs/noir-aztec/src/types.nr b/yarn-project/noir-libs/noir-aztec/src/types.nr index 4614a0c05bd..babc0a6298c 100644 --- a/yarn-project/noir-libs/noir-aztec/src/types.nr +++ b/yarn-project/noir-libs/noir-aztec/src/types.nr @@ -1,3 +1,4 @@ +mod option; // This can/should be moved out into an official noir library mod point; mod vec; // This can/should be moved out into an official noir library -mod option; // This can/should be moved out into an official noir library \ No newline at end of file +mod type_serialisation; \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/types/point.nr b/yarn-project/noir-libs/noir-aztec/src/types/point.nr index 81e48422671..47ea73ffcde 100644 --- a/yarn-project/noir-libs/noir-aztec/src/types/point.nr +++ b/yarn-project/noir-libs/noir-aztec/src/types/point.nr @@ -1,3 +1,5 @@ +use crate::types::type_serialisation::TypeSerialisationInterface; + struct Point { x: Field, y: Field, @@ -7,4 +9,22 @@ impl Point { fn new(x: Field, y: Field) -> Self { Point { x, y } } -} \ No newline at end of file +} + +global POINT_SERIALISED_LEN: Field = 2; + +fn deserialisePoint(fields: [Field; POINT_SERIALISED_LEN]) -> Point { + Point { + x: fields[0], + y: fields[1], + } +} + +fn serialisePoint(point: Point) -> [Field; POINT_SERIALISED_LEN] { + [point.x, point.y] +} + +global PointSerialisationMethods = TypeSerialisationInterface { + deserialise: deserialisePoint, + serialise: serialisePoint, +}; \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr similarity index 92% rename from yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr rename to yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr index d76e52102a5..dfe738d2c38 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr +++ b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation.nr @@ -1,3 +1,4 @@ +mod bool_serialisation; mod field_serialisation; mod u32_serialisation; diff --git a/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/bool_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/bool_serialisation.nr new file mode 100644 index 00000000000..734f725f35b --- /dev/null +++ b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/bool_serialisation.nr @@ -0,0 +1,16 @@ +use crate::types::type_serialisation::TypeSerialisationInterface; + +global BOOL_SERIALISED_LEN: Field = 1; + +fn deserialiseBool(fields: [Field; BOOL_SERIALISED_LEN]) -> bool { + fields[0] as bool +} + +fn serialiseBool(value: bool) -> [Field; BOOL_SERIALISED_LEN] { + [value as Field] +} + +global BoolSerialisationMethods = TypeSerialisationInterface { + deserialise: deserialiseBool, + serialise: serialiseBool, +}; \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/field_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/field_serialisation.nr similarity index 82% rename from yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/field_serialisation.nr rename to yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/field_serialisation.nr index 5352d0e3e5f..5fcaf370523 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/field_serialisation.nr +++ b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/field_serialisation.nr @@ -1,4 +1,4 @@ -use crate::state_vars::type_serialisation::TypeSerialisationInterface; +use crate::types::type_serialisation::TypeSerialisationInterface; global FIELD_SERIALISED_LEN: Field = 1; diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/u32_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/u32_serialisation.nr similarity index 82% rename from yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/u32_serialisation.nr rename to yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/u32_serialisation.nr index 21178a167f2..dd00ebfedfd 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/u32_serialisation.nr +++ b/yarn-project/noir-libs/noir-aztec/src/types/type_serialisation/u32_serialisation.nr @@ -1,4 +1,4 @@ -use crate::state_vars::type_serialisation::TypeSerialisationInterface; +use crate::types::type_serialisation::TypeSerialisationInterface; global U32_SERIALISED_LEN: Field = 1; diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index cd531e7afa5..841c74cf40d 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -523,12 +523,20 @@ __metadata: "@rushstack/eslint-patch": ^1.1.4 "@types/fs-extra": ^11.0.1 "@types/jest": ^29.5.0 + "@types/lodash.camelcase": ^4.3.7 + "@types/lodash.capitalize": ^4.2.7 "@types/lodash.compact": ^3.0.7 + "@types/lodash.times": ^4.3.7 + "@types/lodash.upperfirst": ^4.3.7 "@types/node": ^18.7.23 commander: ^9.0.0 fs-extra: ^11.1.1 jest: ^29.5.0 + lodash.camelcase: ^4.3.0 + lodash.capitalize: ^4.2.1 lodash.compact: ^3.0.1 + lodash.times: ^4.3.2 + lodash.upperfirst: ^4.3.1 toml: ^3.0.0 ts-jest: ^29.1.0 ts-node: ^10.9.1 @@ -3231,6 +3239,15 @@ __metadata: languageName: node linkType: hard +"@types/lodash.capitalize@npm:^4.2.7": + version: 4.2.7 + resolution: "@types/lodash.capitalize@npm:4.2.7" + dependencies: + "@types/lodash": "*" + checksum: dab8b781d7dcc56c18ba0c8286a6ccb61cc598d936a449265453a473e62b2b6d7c109c4447dfeb8ccacc4088769bc3bfd0d39bc8797f03e4e685d4f4b1bc7c01 + languageName: node + linkType: hard + "@types/lodash.chunk@npm:^4.2.7": version: 4.2.7 resolution: "@types/lodash.chunk@npm:4.2.7"