From 316e1d386a0be7cc99993d616d222351ad784637 Mon Sep 17 00:00:00 2001 From: dark64 Date: Tue, 1 Jun 2021 15:40:12 +0200 Subject: [PATCH 01/14] Change endianness in keccak, sha3 and blake2s hash algorithms to big endian --- .../stdlib/hashes/blake2/blake2s_p.zok | 25 +++++++++++++++++-- .../stdlib/hashes/keccak/keccak.zok | 18 ++++++++++++- .../tests/hashes/blake2/blake2s_1024bit.zok | 15 +++++++++-- .../tests/hashes/blake2/blake2s_1536bit.zok | 15 +++++++++-- .../tests/hashes/blake2/blake2s_512bit.zok | 15 +++++++++-- .../tests/hashes/blake2/blake2s_8192bit.zok | 15 +++++++++-- .../tests/tests/hashes/blake2/blake2s_p.zok | 15 +++++++++-- .../tests/tests/hashes/keccak/256bit.zok | 10 +++++++- .../tests/tests/hashes/keccak/384bit.zok | 13 +++++++++- .../tests/tests/hashes/keccak/512bit.zok | 12 +++++++-- .../tests/tests/hashes/sha3/256bit.zok | 10 +++++++- .../tests/tests/hashes/sha3/384bit.zok | 13 +++++++++- .../tests/tests/hashes/sha3/512bit.zok | 12 +++++++-- 13 files changed, 167 insertions(+), 21 deletions(-) diff --git a/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok b/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok index d4754a16..e1bfdf68 100644 --- a/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok +++ b/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok @@ -3,9 +3,17 @@ import "utils/casts/u32_to_bits" import "utils/casts/u32_from_bits" +// right rotation def rotr32(u32 x) -> u32: return (x >> N) | (x << (32 - N)) +// change endianness +def swap_u32(u32 val) -> u32: + return (val << 24) | \ + ((val << 8) & 0x00ff0000) | \ + ((val >> 8) & 0x0000ff00) | \ + ((val >> 24) & 0x000000ff) + def blake2s_iv() -> (u32[8]): return [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, @@ -73,8 +81,8 @@ def blake2s_init(u32[2] p) -> (u32[8]): iv[3], iv[4], iv[5], - iv[6] ^ p[0], - iv[7] ^ p[1] + iv[6] ^ swap_u32(p[0]), + iv[7] ^ swap_u32(p[1]) ] return h @@ -84,6 +92,13 @@ def main(u32[K][16] input, u32[2] p) -> (u32[8]): u32 t0 = 0 u32 t1 = 0 + // change endianness of inputs from big endian to little endian + for u32 i in 0..K do + for u32 j in 0..16 do + input[i][j] = swap_u32(input[i][j]) + endfor + endfor + for u32 i in 0..K-1 do t0 = (i + 1) * 64 t1 = if t0 == 0 then t1 + 1 else t1 fi @@ -94,4 +109,10 @@ def main(u32[K][16] input, u32[2] p) -> (u32[8]): t1 = if t0 == 0 then t1 + 1 else t1 fi h = blake2s_compression(h, input[K - 1], [t0, t1], true) + + // change endianness of output from little endian to big endian + for u32 i in 0..8 do + h[i] = swap_u32(h[i]) + endfor + return h \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok b/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok index 791ef30b..4eb63f64 100644 --- a/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok +++ b/zokrates_stdlib/stdlib/hashes/keccak/keccak.zok @@ -28,6 +28,12 @@ def rc() -> u64[24]: def rotl64(u64 x, u32 n) -> u64: return ((x << n) | (x >> (64 - n))) +// change endianness +def swap_u64(u64 val) -> u64: + val = ((val << 8) & 0xFF00FF00FF00FF00) | ((val >> 8) & 0x00FF00FF00FF00FF) + val = ((val << 16) & 0xFFFF0000FFFF0000) | ((val >> 16) & 0x0000FFFF0000FFFF) + return (val << 32) | (val >> 32) + // compression function def keccakf(u64[25] st) -> u64[25]: u32[24] rotc = rho() @@ -80,6 +86,11 @@ def main(u64[N] input, u64 pad) -> u64[25]: u32 rate = (200 - (W / 4)) / 8 u32 pt = 0 + // change endianness of inputs from big endian to little endian + for u32 i in 0..N do + input[i] = swap_u64(input[i]) + endfor + // update for u32 i in 0..N do q[pt] = q[pt] ^ input[i] @@ -90,6 +101,11 @@ def main(u64[N] input, u64 pad) -> u64[25]: // finalize q[pt] = q[pt] ^ pad q[rate - 1] = q[rate - 1] ^ 0x8000000000000000 - q = keccakf(q) + + // change endianness of output from little endian to big endian + for u32 i in 0..W/64 do + q[i] = swap_u64(q[i]) + endfor + return q \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok index 899f120f..55beccfb 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok @@ -1,6 +1,17 @@ import "hashes/blake2/blake2s" +// Python code: +// >>> from hashlib import blake2s + +// >>> digest = blake2s() +// >>> digest.update(b'\x00' * 128) +// >>> digest.hexdigest() +// '4e420520b981ce7bdbf4ce2c4dbadb9450079b7deb9737b5232957d323f801cb' + def main(): - u32[8] h = blake2s::<2>([[0; 16]; 2]) - assert(h == [0x2005424E, 0x7BCE81B9, 0x2CCEF4DB, 0x94DBBA4D, 0x7D9B0750, 0xB53797EB, 0xD3572923, 0xCB01F823]) + u32[8] h = blake2s::<2>([[0; 16]; 2]) // 2 * 16 * 32 = 1024 bit input + assert(h == [ + 0x4E420520, 0xB981CE7B, 0xDBF4CE2C, 0x4DBADB94, + 0x50079B7D, 0xEB9737B5, 0x232957D3, 0x23F801CB + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok index 28ba1529..61dc35d4 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok @@ -1,6 +1,17 @@ import "hashes/blake2/blake2s" +// Python code: +// >>> from hashlib import blake2s + +// >>> digest = blake2s() +// >>> digest.update(b'\x00\x00\x00\x2A' * 48) +// >>> digest.hexdigest() +// '2707edbde466a6632371e0611804ecdbe3e21dd683ce9d2060c50341b6fa99ed' + def main(): - u32[8] h = blake2s::<3>([[0x42424242; 16]; 3]) - assert(h == [0x804BD0E6, 0x90AD426E, 0x6BCF0BAD, 0xCB2D22C1, 0xF717B3C3, 0x4D9CB47F, 0xEB541A97, 0x061D9ED0]) + u32[8] h = blake2s::<3>([[42; 16]; 3]) // 3 * 16 * 32 = 1536 bit input + assert(h == [ + 0x2707EDBD, 0xE466A663, 0x2371E061, 0x1804ECDB, + 0xE3E21DD6, 0x83CE9D20, 0x60C50341, 0xB6FA99ED + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok index 28d5edca..2971542a 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok @@ -1,6 +1,17 @@ import "hashes/blake2/blake2s" +// Python code: +// >>> from hashlib import blake2s + +// >>> digest = blake2s() +// >>> digest.update(b'\x00' * 64) +// >>> digest.hexdigest() +// 'ae09db7cd54f42b490ef09b6bc541af688e4959bb8c53f359a6f56e38ab454a3' + def main(): - u32[8] h = blake2s::<1>([[0; 16]]) - assert(h == [0x7CDB09AE, 0xB4424FD5, 0xB609EF90, 0xF61A54BC, 0x9B95E488, 0x353FC5B8, 0xE3566F9A, 0xA354B48A]) + u32[8] h = blake2s::<1>([[0; 16]; 1]) // 16 * 32 = 512 bit input + assert(h == [ + 0xAE09DB7C, 0xD54F42B4, 0x90EF09B6, 0xBC541AF6, + 0x88E4959B, 0xB8C53F35, 0x9A6F56E3, 0x8AB454A3 + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok index f7a93b80..8d860131 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok @@ -1,6 +1,17 @@ import "hashes/blake2/blake2s" +// Python code: +// >>> from hashlib import blake2s + +// >>> digest = blake2s() +// >>> digest.update(b'\x00' * 1024) +// >>> digest.hexdigest() +// '035366632a506c045d4a51c833e8b76791d5daa9bca821b4a2732a66fb5aa22d' + def main(): - u32[8] h = blake2s::<16>([[0; 16]; 16]) - assert(h == [0x63665303, 0x046C502A, 0xC8514A5D, 0x67B7E833, 0xA9DAD591, 0xB421A8BC, 0x662A73A2, 0x2DA25AFB]) + u32[8] h = blake2s::<16>([[0; 16]; 16]) // 16 * 16 * 32 = 8192 bit input + assert(h == [ + 0x03536663, 0x2A506C04, 0x5D4A51C8, 0x33E8B767, + 0x91D5DAA9, 0xBCA821B4, 0xA2732A66, 0xFB5AA22D + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok index 7a861e6c..3e83026e 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok @@ -1,6 +1,17 @@ import "hashes/blake2/blake2s_p" as blake2s +// Python code: +// >>> from hashlib import blake2s + +// >>> digest = blake2s(person=b'\x12\x34\x56\x78\x00\x00\x00\x00') +// >>> digest.update(b'\x00' * 64) +// >>> digest.hexdigest() +// 'a6e927d1b9d50453bc6eb5e4050c443a7203a541cc06ba78a7dc00caa69fb3e9' + def main(): - u32[8] h = blake2s::<1>([[0; 16]], [0x12345678, 0]) - assert(h == [0xC63C8C31, 0x5FCA3E69, 0x13850D46, 0x1DE48657, 0x208D2534, 0x9AA6E0EF, 0xAFEE7610, 0xFBDFAC13]) + u32[8] h = blake2s::<1>([[0; 16]; 1], [0x12345678, 0]) + assert(h == [ + 0xA6E927D1, 0xB9D50453, 0xBC6EB5E4, 0x050C443A, + 0x7203A541, 0xCC06BA78, 0xA7DC00CA, 0xA69FB3E9 + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/256bit.zok b/zokrates_stdlib/tests/tests/hashes/keccak/256bit.zok index 36eb3635..84be2d7f 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/256bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/keccak/256bit.zok @@ -1,6 +1,14 @@ import "hashes/keccak/256bit" as keccak256 +// Python code: +// >>> from Crypto.Hash import keccak + +// >>> digest = keccak.new(digest_bits=256) +// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20) +// >>> digest.hexdigest() +// '33d0141407fee6e5d9caf6ae44e840bc67a37da55e3c845fbc2b4a6dce1f02f0' + def main(): u64[4] h = keccak256::<20>([42; 20]) - assert(h == [0x09330DD35B609CA9, 0xDACFC1598C95602C, 0xACD911013FB018F3, 0x17233D68F05E0826]) + assert(h == [0x33D0141407FEE6E5, 0xD9CAF6AE44E840BC, 0x67A37DA55E3C845F, 0xBC2B4A6DCE1F02F0]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/384bit.zok b/zokrates_stdlib/tests/tests/hashes/keccak/384bit.zok index 019bf558..a12a3f96 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/384bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/keccak/384bit.zok @@ -1,6 +1,17 @@ import "hashes/keccak/384bit" as keccak384 +// Python code: +// >>> from Crypto.Hash import keccak + +// >>> digest = keccak.new(digest_bits=384) +// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20) +// >>> digest.hexdigest() +// 'a944b9b859c1e69d66b52d4cf1f678b24ed8a9ccb0a32bbe882af8a3a1acbd3b68eed9c628307e5d3789f1a64a50e8e7' + def main(): u64[6] h = keccak384::<20>([42; 20]) - assert(h == [0x2E9DCE590F0A1908, 0x0C4234AB952C5598, 0xFB2DF066B44780C2, 0x717039E101D4A8DA, 0xBAD1EFE140C4B2C4, 0xFAE08DAC3438416E]) + assert(h == [ + 0xA944B9B859C1E69D, 0x66B52D4CF1F678B2, 0x4ED8A9CCB0A32BBE, + 0x882AF8A3A1ACBD3B, 0x68EED9C628307E5D, 0x3789F1A64A50E8E7 + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/512bit.zok b/zokrates_stdlib/tests/tests/hashes/keccak/512bit.zok index 4e7d3e91..7c46803c 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/512bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/keccak/512bit.zok @@ -1,9 +1,17 @@ import "hashes/keccak/512bit" as keccak512 +// Python code: +// >>> from Crypto.Hash import keccak + +// >>> digest = keccak.new(digest_bits=512) +// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20) +// >>> digest.hexdigest() +// '5451affca80019c7ac9a7ff647ca073b56e19d55857031df14e00bb1d36ed18a05bdac99bcc0417240dea0cf3fddd19144b8d1e9618fd3f6c8f1a79f7e489eb8' + def main(): u64[8] h = keccak512::<20>([42; 20]) assert(h == [ - 0x2716192386255918, 0x68DFF390376BBF13, 0xBD695ADA4CD230E3, 0xF3B00388676A04D3, - 0x484F3F1BB9F36A09, 0x9D0119067282F940, 0xDF27DE0F48072A66, 0xF5957972134160EB + 0x5451AFFCA80019C7, 0xAC9A7FF647CA073B, 0x56E19D55857031DF, 0x14E00BB1D36ED18A, + 0x05BDAC99BCC04172, 0x40DEA0CF3FDDD191, 0x44B8D1E9618FD3F6, 0xC8F1A79F7E489EB8 ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha3/256bit.zok b/zokrates_stdlib/tests/tests/hashes/sha3/256bit.zok index e5988be9..203bb970 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha3/256bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/sha3/256bit.zok @@ -1,6 +1,14 @@ import "hashes/sha3/256bit" as sha3_256 +// Python code: +// >>> from Crypto.Hash import SHA3_256 + +// >>> digest = SHA3_256.new() +// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20) +// >>> digest.hexdigest() +// '18d00c9e97cd5516243b67b243ede9e2cf0d45d3a844d33340bfc4efc9165100' + def main(): u64[4] h = sha3_256::<20>([42; 20]) - assert(h == [0x84350A3A90DED183, 0x70518606C7DC401A, 0x2D44F39C0FCEAC92, 0x3E9533A716130C5A]) + assert(h == [0x18D00C9E97CD5516, 0x243B67B243EDE9E2, 0xCF0D45D3A844D333, 0x40BFC4EFC9165100]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha3/384bit.zok b/zokrates_stdlib/tests/tests/hashes/sha3/384bit.zok index cfc24b4d..172f907d 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha3/384bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/sha3/384bit.zok @@ -1,6 +1,17 @@ import "hashes/sha3/384bit" as sha3_384 +// Python code: +// >>> from Crypto.Hash import SHA3_384 + +// >>> digest = SHA3_384.new() +// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20) +// >>> digest.hexdigest() +// 'fbb5abd69915e316836d438f0e833a3ebd0f2d8a11e17e248c96c77210b183aab0874eaaef37609d2c4a9a37a6e9740f' + def main(): u64[6] h = sha3_384::<20>([42; 20]) - assert(h == [0x75A036FA8B615B37, 0x6C73086BB56F092C, 0x536E658916EC18AE, 0xB2F2EEE620CDF698, 0xB7E904DE62A70A31, 0x84FDAA0665836ADD]) + assert(h == [ + 0xFBB5ABD69915E316, 0x836D438F0E833A3E, 0xBD0F2D8A11E17E24, + 0x8C96C77210B183AA, 0xB0874EAAEF37609D, 0x2C4A9A37A6E9740F + ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha3/512bit.zok b/zokrates_stdlib/tests/tests/hashes/sha3/512bit.zok index b5846a3e..9e65810a 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha3/512bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/sha3/512bit.zok @@ -1,9 +1,17 @@ import "hashes/sha3/512bit" as sha3_512 +// Python code: +// >>> from Crypto.Hash import SHA3_512 + +// >>> digest = SHA3_512.new() +// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20) +// >>> digest.hexdigest() +// '73a0967b68de5ce1093cbd7482fd4de9ccc9c782e2edc71b583d26fe16fb19e3322a2a024b7f6e163fbb1a15161686dd3a39233f9cf8616e7c74e91fa1aa3b2b' + def main(): u64[8] h = sha3_512::<20>([42; 20]) assert(h == [ - 0x22DFD92B47C60DAC, 0xDA47C8C247A84FA2, 0x7C5809F122D6950A, 0x8034D41097680656, - 0xD6D06F820B046994, 0xF62743594A554B88, 0x4966E0821CB4D667, 0x974D4391624C5619 + 0x73A0967B68DE5CE1, 0x093CBD7482FD4DE9, 0xCCC9C782E2EDC71B, 0x583D26FE16FB19E3, + 0x322A2A024B7F6E16, 0x3FBB1A15161686DD, 0x3A39233F9CF8616E, 0x7C74E91FA1AA3B2B ]) return \ No newline at end of file From bde76d6ab8d0a711c61a0f470edd2ca7de8f2bcf Mon Sep 17 00:00:00 2001 From: dark64 Date: Tue, 1 Jun 2021 15:43:40 +0200 Subject: [PATCH 02/14] add changelog --- changelogs/unreleased/906-dark64 | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/906-dark64 diff --git a/changelogs/unreleased/906-dark64 b/changelogs/unreleased/906-dark64 new file mode 100644 index 00000000..44f1b858 --- /dev/null +++ b/changelogs/unreleased/906-dark64 @@ -0,0 +1 @@ +Change endianness in keccak, sha3 and blake2s hash algorithms to big endian \ No newline at end of file From 3d05d7386b963c472ff3e94b570879b797d07c7b Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 7 Jun 2021 16:13:24 +0200 Subject: [PATCH 03/14] add breaking test --- .../tests/tests/constants/import/destination.json | 4 ++++ .../tests/tests/constants/import/destination.zok | 3 +++ zokrates_core_test/tests/tests/constants/import/origin.zok | 3 +++ 3 files changed, 10 insertions(+) create mode 100644 zokrates_core_test/tests/tests/constants/import/destination.json create mode 100644 zokrates_core_test/tests/tests/constants/import/destination.zok create mode 100644 zokrates_core_test/tests/tests/constants/import/origin.zok diff --git a/zokrates_core_test/tests/tests/constants/import/destination.json b/zokrates_core_test/tests/tests/constants/import/destination.json new file mode 100644 index 00000000..552e9778 --- /dev/null +++ b/zokrates_core_test/tests/tests/constants/import/destination.json @@ -0,0 +1,4 @@ +{ + "entry_point": "./tests/tests/constants/import/destination.zok", + "tests": [] +} diff --git a/zokrates_core_test/tests/tests/constants/import/destination.zok b/zokrates_core_test/tests/tests/constants/import/destination.zok new file mode 100644 index 00000000..b8236f53 --- /dev/null +++ b/zokrates_core_test/tests/tests/constants/import/destination.zok @@ -0,0 +1,3 @@ +from "./origin.zok" import foo +def main(): + return \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/constants/import/origin.zok b/zokrates_core_test/tests/tests/constants/import/origin.zok new file mode 100644 index 00000000..b1a7d63d --- /dev/null +++ b/zokrates_core_test/tests/tests/constants/import/origin.zok @@ -0,0 +1,3 @@ +const u32 N = 42 +def foo(field[N] a) -> bool: + return true \ No newline at end of file From 46cc73d735efb1751d5a881bda9ad7f4f4fa97a0 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 8 Jun 2021 10:12:37 +0200 Subject: [PATCH 04/14] wip --- zokrates_core/src/embed.rs | 15 +- zokrates_core/src/semantics.rs | 42 ++-- .../src/static_analysis/constant_inliner.rs | 209 +++++++++--------- zokrates_core/src/static_analysis/mod.rs | 1 + .../src/static_analysis/reducer/mod.rs | 18 +- zokrates_core/src/typed_absy/folder.rs | 51 ++++- zokrates_core/src/typed_absy/mod.rs | 23 +- zokrates_core/src/typed_absy/parameter.rs | 4 +- zokrates_core/src/typed_absy/result_folder.rs | 44 +++- zokrates_core/src/typed_absy/types.rs | 89 +++++--- zokrates_core/src/typed_absy/variable.rs | 4 +- .../tests/constants/import/destination.zok | 3 +- .../tests/tests/constants/import/origin.zok | 2 +- 13 files changed, 313 insertions(+), 192 deletions(-) diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 8a782e34..b3ac31a0 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -4,7 +4,8 @@ use crate::flat_absy::{ }; use crate::solvers::Solver; use crate::typed_absy::types::{ - ConcreteGenericsAssignment, Constant, DeclarationSignature, DeclarationType, GenericIdentifier, + ConcreteGenericsAssignment, DeclarationConstant, DeclarationSignature, DeclarationType, + GenericIdentifier, }; use std::collections::HashMap; use zokrates_field::{Bn128Field, Field}; @@ -43,10 +44,12 @@ impl FlatEmbed { .inputs(vec![DeclarationType::uint(32)]) .outputs(vec![DeclarationType::FieldElement]), FlatEmbed::Unpack => DeclarationSignature::new() - .generics(vec![Some(Constant::Generic(GenericIdentifier { - name: "N", - index: 0, - }))]) + .generics(vec![Some(DeclarationConstant::Generic( + GenericIdentifier { + name: "N", + index: 0, + }, + ))]) .inputs(vec![DeclarationType::FieldElement]) .outputs(vec![DeclarationType::array(( DeclarationType::Boolean, @@ -122,7 +125,7 @@ impl FlatEmbed { .generics .into_iter() .map(|c| match c.unwrap() { - Constant::Generic(g) => g, + DeclarationConstant::Generic(g) => g, _ => unreachable!(), }); diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 8fc13972..46e43caa 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -19,9 +19,9 @@ use crate::parser::Position; use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; use crate::typed_absy::types::{ - ArrayType, Constant, DeclarationArrayType, DeclarationFunctionKey, DeclarationSignature, - DeclarationStructMember, DeclarationStructType, DeclarationType, GenericIdentifier, - StructLocation, + ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationFunctionKey, + DeclarationSignature, DeclarationStructMember, DeclarationStructType, DeclarationType, + GenericIdentifier, StructLocation, }; use std::hash::{Hash, Hasher}; @@ -55,8 +55,7 @@ impl ErrorInner { } type TypeMap<'ast> = HashMap>>; -type ConstantMap<'ast, T> = - HashMap, Type<'ast, T>>>; +type ConstantMap<'ast, T> = HashMap>>; /// The global state of the program during semantic checks #[derive(Debug)] @@ -506,8 +505,10 @@ impl<'ast, T: Field> Checker<'ast, T> { .in_file(module_id), ), true => { - constants - .insert(declaration.id, TypedConstantSymbol::Here(c.clone())); + constants.insert( + ConstantIdentifier::new(declaration.id, module_id.into()), + TypedConstantSymbol::Here(c.clone()), + ); self.insert_into_scope(Variable::with_id_and_type( declaration.id, c.get_type(), @@ -600,7 +601,9 @@ impl<'ast, T: Field> Checker<'ast, T> { .constants .entry(import.module_id.to_path_buf()) .or_default() - .get(import.symbol_id) + .iter() + .find(|(i, _)| *i == &import.symbol_id) + .map(|(_, c)| c) .cloned(); match (function_candidates.len(), type_candidate, const_candidate) { @@ -653,8 +656,11 @@ impl<'ast, T: Field> Checker<'ast, T> { }}); } true => { - constants.insert(declaration.id, TypedConstantSymbol::There(import.module_id.to_path_buf(), import.symbol_id)); - self.insert_into_scope(Variable::with_id_and_type(declaration.id, ty.clone())); + let imported_id = ConstantIdentifier::new(import.symbol_id.into(), import.module_id); + let id = ConstantIdentifier::new(declaration.id.clone(), module_id.into()); + + constants.insert(id.clone(), TypedConstantSymbol::There(imported_id)); + self.insert_into_scope(Variable::with_id_and_type(declaration.id.clone(), ty.clone())); state .constants @@ -856,7 +862,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let v = Variable::with_id_and_type( match generic { - Constant::Generic(g) => g.name, + DeclarationConstant::Generic(g) => g.name, _ => unreachable!(), }, Type::Uint(UBitwidth::B32), @@ -996,7 +1002,7 @@ impl<'ast, T: Field> Checker<'ast, T> { } else { match generics_map.insert(g.value, index).is_none() { true => { - generics.push(Some(Constant::Generic(GenericIdentifier { + generics.push(Some(DeclarationConstant::Generic(GenericIdentifier { name: g.value, index, }))); @@ -1112,16 +1118,16 @@ impl<'ast, T: Field> Checker<'ast, T> { fn check_generic_expression( &mut self, expr: ExpressionNode<'ast>, - constants_map: &HashMap, Type<'ast, T>>, + constants_map: &HashMap<&'ast str, Type<'ast, T>>, generics_map: &HashMap, usize>, - ) -> Result, ErrorInner> { + ) -> Result, ErrorInner> { let pos = expr.pos(); match expr.value { - Expression::U32Constant(c) => Ok(Constant::Concrete(c)), + Expression::U32Constant(c) => Ok(DeclarationConstant::Concrete(c)), Expression::IntConstant(c) => { if c <= BigUint::from(2u128.pow(32) - 1) { - Ok(Constant::Concrete( + Ok(DeclarationConstant::Concrete( u32::from_str_radix(&c.to_str_radix(16), 16).unwrap(), )) } else { @@ -1138,7 +1144,7 @@ impl<'ast, T: Field> Checker<'ast, T> { match (constants_map.get(name), generics_map.get(&name)) { (Some(ty), None) => { match ty { - Type::Uint(UBitwidth::B32) => Ok(Constant::Identifier(name, 32usize)), + Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Identifier(name)), _ => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1148,7 +1154,7 @@ impl<'ast, T: Field> Checker<'ast, T> { }) } } - (None, Some(index)) => Ok(Constant::Generic(GenericIdentifier { name, index: *index })), + (None, Some(index)) => Ok(DeclarationConstant::Generic(GenericIdentifier { name, index: *index })), _ => Err(ErrorInner { pos: Some(pos), message: format!("Undeclared symbol `{}` in function definition", name) diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index b6f22cce..182c201f 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -1,43 +1,41 @@ -use crate::static_analysis::propagation::Propagator; use crate::typed_absy::folder::*; -use crate::typed_absy::result_folder::ResultFolder; -use crate::typed_absy::types::{Constant, DeclarationStructType, GStructMember}; +use crate::typed_absy::types::DeclarationConstant; use crate::typed_absy::*; +use core::str; use std::collections::HashMap; use std::convert::TryInto; use zokrates_field::Field; -pub struct ConstantInliner<'ast, 'a, T: Field> { +type ModuleConstants<'ast, T> = + HashMap>>; + +pub struct ConstantInliner<'ast, T> { modules: TypedModules<'ast, T>, location: OwnedTypedModuleId, - propagator: Propagator<'ast, 'a, T>, + constants: ModuleConstants<'ast, T>, } -impl<'ast, 'a, T: Field> ConstantInliner<'ast, 'a, T> { +impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { pub fn new( modules: TypedModules<'ast, T>, location: OwnedTypedModuleId, - propagator: Propagator<'ast, 'a, T>, + constants: ModuleConstants<'ast, T>, ) -> Self { ConstantInliner { modules, location, - propagator, + constants, } } pub fn inline(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { - let mut constants = HashMap::new(); - let mut inliner = ConstantInliner::new( - p.modules.clone(), - p.main.clone(), - Propagator::with_constants(&mut constants), - ); + let constants = HashMap::new(); + let mut inliner = ConstantInliner::new(p.modules.clone(), p.main.clone(), constants); inliner.fold_program(p) } - fn module(&self) -> &TypedModule<'ast, T> { - self.modules.get(&self.location).unwrap() - } + // fn module(&self) -> &TypedModule<'ast, T> { + // self.modules.get(&self.location).unwrap() + // } fn change_location(&mut self, location: OwnedTypedModuleId) -> OwnedTypedModuleId { let prev = self.location.clone(); @@ -46,116 +44,119 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, 'a, T> { } fn get_constant(&mut self, id: &Identifier) -> Option> { - self.modules - .get(&self.location) - .unwrap() - .constants - .get(id.clone().try_into().unwrap()) - .cloned() - .map(|symbol| self.get_canonical_constant(symbol)) - } - - fn get_canonical_constant( - &mut self, - symbol: TypedConstantSymbol<'ast, T>, - ) -> TypedConstant<'ast, T> { - match symbol { - TypedConstantSymbol::There(module_id, id) => { - let location = self.change_location(module_id); - let symbol = self.module().constants.get(id).cloned().unwrap(); - - let symbol = self.get_canonical_constant(symbol); - let _ = self.change_location(location); - symbol - } - TypedConstantSymbol::Here(tc) => { - let tc: TypedConstant = self.fold_constant(tc); - TypedConstant { - expression: self.propagator.fold_expression(tc.expression).unwrap(), - ..tc - } + assert_eq!(id.version, 0); + match id.id { + CoreIdentifier::Call(..) => { + unreachable!("calls indentifiers are only available after call inlining") } + CoreIdentifier::Source(id) => self + .constants + .get(&self.location) + .and_then(|constants| constants.get(id)) + .cloned(), } } } -impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> { +impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { fn fold_program(&mut self, p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { TypedProgram { modules: p .modules .into_iter() - .map(|(module_id, module)| { - self.change_location(module_id.clone()); - (module_id, self.fold_module(module)) + .map(|(m_id, m)| { + self.change_location(m_id.clone()); + (m_id, self.fold_module(m)) }) .collect(), - main: p.main, + ..p } } - fn fold_declaration_type(&mut self, t: DeclarationType<'ast>) -> DeclarationType<'ast> { - match t { - DeclarationType::Array(ref array_ty) => match array_ty.size { - Constant::Identifier(name, _) => { - let tc = self.get_constant(&name.into()).unwrap(); - let expression: UExpression<'ast, T> = tc.expression.try_into().unwrap(); - match expression.inner { - UExpressionInner::Value(v) => DeclarationType::array(( - self.fold_declaration_type(*array_ty.ty.clone()), - Constant::Concrete(v as u32), - )), - _ => unreachable!("expected u32 value"), - } - } - _ => t, - }, - DeclarationType::Struct(struct_ty) => DeclarationType::struc(DeclarationStructType { - members: struct_ty - .members + fn fold_module(&mut self, m: TypedModule<'ast, T>) -> TypedModule<'ast, T> { + // only treat this module if its constants are not in the map yet + if !self.constants.contains_key(&self.location) { + self.constants.entry(self.location.clone()).or_default(); + TypedModule { + constants: m + .constants .into_iter() - .map(|m| GStructMember::new(m.id, self.fold_declaration_type(*m.ty))) - .collect(), - ..struct_ty - }), - _ => t, - } - } + .map(|(id, tc)| { + let constant = match tc { + TypedConstantSymbol::There(imported_id) => { + if !self.constants.contains_key(&imported_id.module) { + let current_m_id = self.change_location(id.module.clone()); + let _ = self + .fold_module(self.modules.get(&id.module).unwrap().clone()); + self.change_location(current_m_id); + } + self.constants + .get(&imported_id.module) + .unwrap() + .get(&imported_id.id) + .cloned() + .unwrap() + } + TypedConstantSymbol::Here(c) => fold_constant(self, c), + }; - fn fold_type(&mut self, t: Type<'ast, T>) -> Type<'ast, T> { - use self::GType::*; - match t { - Array(ref array_type) => match &array_type.size.inner { - UExpressionInner::Identifier(v) => match self.get_constant(v) { - Some(tc) => { - let expression: UExpression<'ast, T> = tc.expression.try_into().unwrap(); - Type::array(GArrayType::new( - self.fold_type(*array_type.ty.clone()), - expression, - )) - } - None => t, - }, - _ => t, - }, - Struct(struct_type) => Type::struc(GStructType { - members: struct_type - .members + assert!(self + .constants + .entry(self.location.clone()) + .or_default() + .insert(id.id, constant.clone()) + .is_none()); + + (id, TypedConstantSymbol::Here(constant)) + }) + .collect(), + functions: m + .functions .into_iter() - .map(|m| GStructMember::new(m.id, self.fold_type(*m.ty))) + .map(|(key, fun)| { + ( + self.fold_declaration_function_key(key), + self.fold_function_symbol(fun), + ) + }) .collect(), - ..struct_type - }), - _ => t, + } + } else { + m } } - fn fold_constant_symbol( + fn fold_declaration_constant( &mut self, - s: TypedConstantSymbol<'ast, T>, - ) -> TypedConstantSymbol<'ast, T> { - let tc = self.get_canonical_constant(s); - TypedConstantSymbol::Here(tc) + c: DeclarationConstant<'ast>, + ) -> DeclarationConstant<'ast> { + println!("id {}", c); + println!("constants {:#?}", self.constants); + println!("location {}", self.location.display()); + + match c { + DeclarationConstant::Identifier(id) => DeclarationConstant::Concrete( + match self + .constants + .get(&self.location) + .unwrap() + .get(&id) + .cloned() + .unwrap() + { + TypedConstant { + ty: Type::Uint(UBitwidth::B32), + expression: + TypedExpression::Uint(UExpression { + inner: UExpressionInner::Value(v), + .. + }), + } => v as u32, + _ => unreachable!(), + }, + ), + c => c, + } } fn fold_field_expression( diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index 598f0973..256f19fe 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -78,6 +78,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> { // inline user-defined constants let r = ConstantInliner::inline(self); + println!("{}", r); // isolate branches let r = if config.isolate_branches { Isolator::isolate(r) diff --git a/zokrates_core/src/static_analysis/reducer/mod.rs b/zokrates_core/src/static_analysis/reducer/mod.rs index ac3037dd..ae26d6cd 100644 --- a/zokrates_core/src/static_analysis/reducer/mod.rs +++ b/zokrates_core/src/static_analysis/reducer/mod.rs @@ -614,7 +614,7 @@ fn compute_hash(f: &TypedFunction) -> u64 { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::types::Constant; + use crate::typed_absy::types::DeclarationConstant; use crate::typed_absy::types::DeclarationSignature; use crate::typed_absy::{ ArrayExpression, ArrayExpressionInner, DeclarationFunctionKey, DeclarationType, @@ -834,11 +834,11 @@ mod tests { )]) .inputs(vec![DeclarationType::array(( DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ))]) .outputs(vec![DeclarationType::array(( DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ))]); let foo: TypedFunction = TypedFunction { @@ -1053,11 +1053,11 @@ mod tests { )]) .inputs(vec![DeclarationType::array(( DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ))]) .outputs(vec![DeclarationType::array(( DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ))]); let foo: TypedFunction = TypedFunction { @@ -1285,11 +1285,11 @@ mod tests { let foo_signature = DeclarationSignature::new() .inputs(vec![DeclarationType::array(( DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ))]) .outputs(vec![DeclarationType::array(( DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ))]) .generics(vec![Some( GenericIdentifier::with_name("K").index(0).into(), @@ -1299,7 +1299,7 @@ mod tests { arguments: vec![DeclarationVariable::array( "a", DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ) .into()], statements: vec![ @@ -1363,7 +1363,7 @@ mod tests { arguments: vec![DeclarationVariable::array( "a", DeclarationType::FieldElement, - Constant::Generic(GenericIdentifier::with_name("K").index(0)), + DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)), ) .into()], statements: vec![TypedStatement::Return(vec![ diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index d80b3bca..2777bea0 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -1,6 +1,6 @@ // Generic walk through a typed AST. Not mutating in place -use crate::typed_absy::types::{ArrayType, StructMember, StructType}; +use crate::typed_absy::types::*; use crate::typed_absy::*; use zokrates_field::Field; @@ -80,6 +80,13 @@ pub trait Folder<'ast, T: Field>: Sized { fold_signature(self, s) } + fn fold_declaration_constant( + &mut self, + c: DeclarationConstant<'ast>, + ) -> DeclarationConstant<'ast> { + fold_declaration_constant(self, c) + } + fn fold_parameter(&mut self, p: DeclarationParameter<'ast>) -> DeclarationParameter<'ast> { DeclarationParameter { id: self.fold_declaration_variable(p.id), @@ -144,7 +151,40 @@ pub trait Folder<'ast, T: Field>: Sized { } fn fold_declaration_type(&mut self, t: DeclarationType<'ast>) -> DeclarationType<'ast> { - t + use self::GType::*; + + match t { + Array(array_type) => Array(self.fold_declaration_array_type(array_type)), + Struct(struct_type) => Struct(self.fold_declaration_struct_type(struct_type)), + t => t, + } + } + + fn fold_declaration_array_type( + &mut self, + t: DeclarationArrayType<'ast>, + ) -> DeclarationArrayType<'ast> { + DeclarationArrayType { + ty: box self.fold_declaration_type(*t.ty), + size: self.fold_declaration_constant(t.size), + } + } + + fn fold_declaration_struct_type( + &mut self, + t: DeclarationStructType<'ast>, + ) -> DeclarationStructType<'ast> { + DeclarationStructType { + members: t + .members + .into_iter() + .map(|m| DeclarationStructMember { + ty: box self.fold_declaration_type(*m.ty), + ..m + }) + .collect(), + ..t + } } fn fold_assignee(&mut self, a: TypedAssignee<'ast, T>) -> TypedAssignee<'ast, T> { @@ -880,6 +920,13 @@ fn fold_signature<'ast, T: Field, F: Folder<'ast, T>>( } } +fn fold_declaration_constant<'ast, T: Field, F: Folder<'ast, T>>( + _: &mut F, + c: DeclarationConstant<'ast>, +) -> DeclarationConstant<'ast> { + c +} + pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>( f: &mut F, e: ArrayExpression<'ast, T>, diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index cdfecc3e..3bdf36b8 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -19,9 +19,9 @@ mod variable; pub use self::identifier::CoreIdentifier; pub use self::parameter::{DeclarationParameter, GParameter}; pub use self::types::{ - ConcreteFunctionKey, ConcreteSignature, ConcreteType, DeclarationFunctionKey, - DeclarationSignature, DeclarationType, GArrayType, GStructType, GType, GenericIdentifier, - IntoTypes, Signature, StructType, Type, Types, UBitwidth, + ConcreteFunctionKey, ConcreteSignature, ConcreteType, ConstantIdentifier, + DeclarationFunctionKey, DeclarationSignature, DeclarationType, GArrayType, GStructType, GType, + GenericIdentifier, IntoTypes, Signature, StructType, Type, Types, UBitwidth, }; use crate::typed_absy::types::ConcreteGenericsAssignment; @@ -62,12 +62,10 @@ pub type TypedModules<'ast, T> = HashMap = HashMap, TypedFunctionSymbol<'ast, T>>; -pub type ConstantIdentifier<'ast> = &'ast str; - #[derive(Clone, Debug, PartialEq)] pub enum TypedConstantSymbol<'ast, T> { Here(TypedConstant<'ast, T>), - There(OwnedTypedModuleId, ConstantIdentifier<'ast>), + There(ConstantIdentifier<'ast>), } /// A collection of `TypedConstantSymbol`s @@ -188,12 +186,17 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedModule<'ast, T> { let res = self .constants .iter() - .map(|(key, symbol)| match symbol { + .map(|(id, symbol)| match symbol { TypedConstantSymbol::Here(ref tc) => { - format!("const {} {} = {}", tc.ty, key, tc.expression) + format!("const {} {} = {}", tc.ty, id.id, tc.expression) } - TypedConstantSymbol::There(ref module_id, ref id) => { - format!("from \"{}\" import {} as {}", module_id.display(), id, key) + TypedConstantSymbol::There(ref imported_id) => { + format!( + "from \"{}\" import {} as {}", + imported_id.module.display(), + imported_id.id, + id.id + ) } }) .chain(self.functions.iter().map(|(key, symbol)| match symbol { diff --git a/zokrates_core/src/typed_absy/parameter.rs b/zokrates_core/src/typed_absy/parameter.rs index 6a41c0e2..45421945 100644 --- a/zokrates_core/src/typed_absy/parameter.rs +++ b/zokrates_core/src/typed_absy/parameter.rs @@ -1,4 +1,4 @@ -use crate::typed_absy::types::Constant; +use crate::typed_absy::types::DeclarationConstant; use crate::typed_absy::GVariable; use std::fmt; @@ -18,7 +18,7 @@ impl<'ast, S> From> for GParameter<'ast, S> { } } -pub type DeclarationParameter<'ast> = GParameter<'ast, Constant<'ast>>; +pub type DeclarationParameter<'ast> = GParameter<'ast, DeclarationConstant<'ast>>; impl<'ast, S: fmt::Display + Clone> fmt::Display for GParameter<'ast, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_core/src/typed_absy/result_folder.rs index bdb334b1..cbca2f7e 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_core/src/typed_absy/result_folder.rs @@ -1,6 +1,6 @@ // Generic walk through a typed AST. Not mutating in place -use crate::typed_absy::types::{ArrayType, StructMember, StructType}; +use crate::typed_absy::types::*; use crate::typed_absy::*; use zokrates_field::Field; @@ -97,6 +97,13 @@ pub trait ResultFolder<'ast, T: Field>: Sized { fold_signature(self, s) } + fn fold_declaration_constant( + &mut self, + c: DeclarationConstant<'ast>, + ) -> Result, Self::Error> { + fold_declaration_constant(self, c) + } + fn fold_parameter( &mut self, p: DeclarationParameter<'ast>, @@ -214,6 +221,34 @@ pub trait ResultFolder<'ast, T: Field>: Sized { Ok(t) } + fn fold_declaration_array_type( + &mut self, + t: DeclarationArrayType<'ast>, + ) -> Result, Self::Error> { + Ok(DeclarationArrayType { + ty: box self.fold_declaration_type(*t.ty)?, + size: self.fold_declaration_constant(t.size)?, + }) + } + + fn fold_declaration_struct_type( + &mut self, + t: DeclarationStructType<'ast>, + ) -> Result, Self::Error> { + Ok(DeclarationStructType { + members: t + .members + .into_iter() + .map(|m| { + let id = m.id; + self.fold_declaration_type(*m.ty) + .map(|ty| DeclarationStructMember { ty: box ty, id }) + }) + .collect::>()?, + ..t + }) + } + fn fold_assignee( &mut self, a: TypedAssignee<'ast, T>, @@ -934,6 +969,13 @@ fn fold_signature<'ast, T: Field, F: ResultFolder<'ast, T>>( }) } +fn fold_declaration_constant<'ast, T: Field, F: ResultFolder<'ast, T>>( + _: &mut F, + c: DeclarationConstant<'ast>, +) -> Result, F::Error> { + Ok(c) +} + pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>( f: &mut F, e: ArrayExpression<'ast, T>, diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 4b6453eb..8a64927f 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -101,37 +101,49 @@ impl<'ast> fmt::Display for GenericIdentifier<'ast> { #[derive(Debug)] pub struct SpecializationError; +#[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] +pub struct ConstantIdentifier<'ast> { + pub module: OwnedTypedModuleId, + pub id: &'ast str, +} + +impl<'ast> ConstantIdentifier<'ast> { + pub fn new(id: &'ast str, module: OwnedTypedModuleId) -> Self { + ConstantIdentifier { id, module } + } +} + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Constant<'ast> { +pub enum DeclarationConstant<'ast> { Generic(GenericIdentifier<'ast>), Concrete(u32), - Identifier(&'ast str, usize), + Identifier(&'ast str), } -impl<'ast> From for Constant<'ast> { +impl<'ast> From for DeclarationConstant<'ast> { fn from(e: u32) -> Self { - Constant::Concrete(e) + DeclarationConstant::Concrete(e) } } -impl<'ast> From for Constant<'ast> { +impl<'ast> From for DeclarationConstant<'ast> { fn from(e: usize) -> Self { - Constant::Concrete(e as u32) + DeclarationConstant::Concrete(e as u32) } } -impl<'ast> From> for Constant<'ast> { +impl<'ast> From> for DeclarationConstant<'ast> { fn from(e: GenericIdentifier<'ast>) -> Self { - Constant::Generic(e) + DeclarationConstant::Generic(e) } } -impl<'ast> fmt::Display for Constant<'ast> { +impl<'ast> fmt::Display for DeclarationConstant<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Constant::Generic(i) => write!(f, "{}", i), - Constant::Concrete(v) => write!(f, "{}", v), - Constant::Identifier(v, _) => write!(f, "{}", v), + DeclarationConstant::Generic(i) => write!(f, "{}", i), + DeclarationConstant::Concrete(v) => write!(f, "{}", v), + DeclarationConstant::Identifier(v) => write!(f, "{}", v), } } } @@ -142,16 +154,17 @@ impl<'ast, T> From for UExpression<'ast, T> { } } -impl<'ast, T> From> for UExpression<'ast, T> { - fn from(c: Constant<'ast>) -> Self { +impl<'ast, T> From> for UExpression<'ast, T> { + fn from(c: DeclarationConstant<'ast>) -> Self { match c { - Constant::Generic(i) => { + DeclarationConstant::Generic(i) => { UExpressionInner::Identifier(i.name.into()).annotate(UBitwidth::B32) } - Constant::Concrete(v) => UExpressionInner::Value(v as u128).annotate(UBitwidth::B32), - Constant::Identifier(v, size) => { - UExpressionInner::Identifier(Identifier::from(v)).annotate(UBitwidth::from(size)) + DeclarationConstant::Concrete(v) => { + UExpressionInner::Value(v as u128).annotate(UBitwidth::B32) } + DeclarationConstant::Identifier(v) => UExpressionInner::Identifier(Identifier::from(v)) + .annotate(UBitwidth::from(UBitwidth::B32)), } } } @@ -169,12 +182,12 @@ impl<'ast, T> TryInto for UExpression<'ast, T> { } } -impl<'ast> TryInto for Constant<'ast> { +impl<'ast> TryInto for DeclarationConstant<'ast> { type Error = SpecializationError; fn try_into(self) -> Result { match self { - Constant::Concrete(v) => Ok(v as usize), + DeclarationConstant::Concrete(v) => Ok(v as usize), _ => Err(SpecializationError), } } @@ -190,7 +203,7 @@ pub struct GStructMember { pub ty: Box>, } -pub type DeclarationStructMember<'ast> = GStructMember>; +pub type DeclarationStructMember<'ast> = GStructMember>; pub type ConcreteStructMember = GStructMember; pub type StructMember<'ast, T> = GStructMember>; @@ -242,7 +255,7 @@ pub struct GArrayType { pub ty: Box>, } -pub type DeclarationArrayType<'ast> = GArrayType>; +pub type DeclarationArrayType<'ast> = GArrayType>; pub type ConcreteArrayType = GArrayType; pub type ArrayType<'ast, T> = GArrayType>; @@ -250,7 +263,7 @@ impl<'ast, T: PartialEq> PartialEq> for ArrayType<'as fn eq(&self, other: &DeclarationArrayType<'ast>) -> bool { *self.ty == *other.ty && match (self.size.as_inner(), &other.size) { - (UExpressionInner::Value(l), Constant::Concrete(r)) => *l as u32 == *r, + (UExpressionInner::Value(l), DeclarationConstant::Concrete(r)) => *l as u32 == *r, _ => true, } } @@ -349,7 +362,7 @@ pub struct GStructType { pub members: Vec>, } -pub type DeclarationStructType<'ast> = GStructType>; +pub type DeclarationStructType<'ast> = GStructType>; pub type ConcreteStructType = GStructType; pub type StructType<'ast, T> = GStructType>; @@ -588,7 +601,7 @@ impl<'de, S: Deserialize<'de>> Deserialize<'de> for GType { } } -pub type DeclarationType<'ast> = GType>; +pub type DeclarationType<'ast> = GType>; pub type ConcreteType = GType; pub type Type<'ast, T> = GType>; @@ -711,7 +724,7 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> { // check the size if types match match (&l.size.as_inner(), &r.size) { // compare the sizes for concrete ones - (UExpressionInner::Value(v), Constant::Concrete(c)) => { + (UExpressionInner::Value(v), DeclarationConstant::Concrete(c)) => { (*v as u32) == *c } _ => true, @@ -772,7 +785,7 @@ pub struct GFunctionKey<'ast, S> { pub signature: GSignature, } -pub type DeclarationFunctionKey<'ast> = GFunctionKey<'ast, Constant<'ast>>; +pub type DeclarationFunctionKey<'ast> = GFunctionKey<'ast, DeclarationConstant<'ast>>; pub type ConcreteFunctionKey<'ast> = GFunctionKey<'ast, usize>; pub type FunctionKey<'ast, T> = GFunctionKey<'ast, UExpression<'ast, T>>; @@ -948,7 +961,7 @@ pub mod signature { } } - pub type DeclarationSignature<'ast> = GSignature>; + pub type DeclarationSignature<'ast> = GSignature>; pub type ConcreteSignature = GSignature; pub type Signature<'ast, T> = GSignature>; @@ -968,15 +981,17 @@ pub mod signature { && match &t0.size { // if the declared size is an identifier, we insert into the map, or check if the concrete size // matches if this identifier is already in the map - Constant::Generic(id) => match constants.0.entry(id.clone()) { + DeclarationConstant::Generic(id) => match constants.0.entry(id.clone()) { Entry::Occupied(e) => *e.get() == s1, Entry::Vacant(e) => { e.insert(s1); true } }, - Constant::Concrete(s0) => s1 == *s0 as usize, - Constant::Identifier(_, s0) => s1 == *s0, + DeclarationConstant::Concrete(s0) => s1 == *s0 as usize, + // in the case of a constant, we do not know the value yet, so we optimistically assume it's correct + // if it does not match, it will be caught during inlining + DeclarationConstant::Identifier(..) => true, } } (DeclarationType::FieldElement, GType::FieldElement) @@ -1000,9 +1015,11 @@ pub mod signature { let ty = box specialize_type(*t0.ty, &constants)?; let size = match t0.size { - Constant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), - Constant::Concrete(s) => Ok(s.into()), - Constant::Identifier(_, s) => Ok((s as u32).into()), + DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), + DeclarationConstant::Concrete(s) => Ok(s.into()), + DeclarationConstant::Identifier(..) => { + unreachable!("identifiers should have been removed in constant inlining") + } }?; GType::Array(GArrayType { size, ty }) @@ -1053,7 +1070,7 @@ pub mod signature { assert_eq!(self.generics.len(), values.len()); let decl_generics = self.generics.iter().map(|g| match g.clone().unwrap() { - Constant::Generic(g) => g, + DeclarationConstant::Generic(g) => g, _ => unreachable!(), }); @@ -1096,7 +1113,7 @@ pub mod signature { v.map(|v| { ( match g.clone().unwrap() { - Constant::Generic(g) => g, + DeclarationConstant::Generic(g) => g, _ => unreachable!(), }, v, diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_core/src/typed_absy/variable.rs index 9151dfdc..27ced917 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_core/src/typed_absy/variable.rs @@ -1,4 +1,4 @@ -use crate::typed_absy::types::{Constant, GStructType, UBitwidth}; +use crate::typed_absy::types::{DeclarationConstant, GStructType, UBitwidth}; use crate::typed_absy::types::{GType, SpecializationError}; use crate::typed_absy::Identifier; use crate::typed_absy::UExpression; @@ -11,7 +11,7 @@ pub struct GVariable<'ast, S> { pub _type: GType, } -pub type DeclarationVariable<'ast> = GVariable<'ast, Constant<'ast>>; +pub type DeclarationVariable<'ast> = GVariable<'ast, DeclarationConstant<'ast>>; pub type ConcreteVariable<'ast> = GVariable<'ast, usize>; pub type Variable<'ast, T> = GVariable<'ast, UExpression<'ast, T>>; diff --git a/zokrates_core_test/tests/tests/constants/import/destination.zok b/zokrates_core_test/tests/tests/constants/import/destination.zok index b8236f53..f0734bc8 100644 --- a/zokrates_core_test/tests/tests/constants/import/destination.zok +++ b/zokrates_core_test/tests/tests/constants/import/destination.zok @@ -1,3 +1,4 @@ from "./origin.zok" import foo def main(): - return \ No newline at end of file + assert(foo([1, 1])) + return \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/constants/import/origin.zok b/zokrates_core_test/tests/tests/constants/import/origin.zok index b1a7d63d..e48514af 100644 --- a/zokrates_core_test/tests/tests/constants/import/origin.zok +++ b/zokrates_core_test/tests/tests/constants/import/origin.zok @@ -1,3 +1,3 @@ -const u32 N = 42 +const u32 N = 1 def foo(field[N] a) -> bool: return true \ No newline at end of file From 212d06ec76d9a3441fba4290a31e0a30cef6e432 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 8 Jun 2021 11:04:15 +0200 Subject: [PATCH 05/14] rename, clippy --- zokrates_core/src/semantics.rs | 20 +++++++++------ .../src/static_analysis/constant_inliner.rs | 2 +- zokrates_core/src/typed_absy/mod.rs | 11 ++++---- zokrates_core/src/typed_absy/types.rs | 25 +++++++++++-------- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 46e43caa..37c4baeb 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -55,7 +55,8 @@ impl ErrorInner { } type TypeMap<'ast> = HashMap>>; -type ConstantMap<'ast, T> = HashMap>>; +type ConstantMap<'ast, T> = + HashMap, Type<'ast, T>>>; /// The global state of the program during semantic checks #[derive(Debug)] @@ -349,7 +350,7 @@ impl<'ast, T: Field> Checker<'ast, T> { fn check_constant_definition( &mut self, - id: &'ast str, + id: ConstantIdentifier<'ast>, c: ConstantDefinitionNode<'ast>, module_id: &ModuleId, state: &State<'ast, T>, @@ -445,7 +446,7 @@ impl<'ast, T: Field> Checker<'ast, T> { module_id: &ModuleId, state: &mut State<'ast, T>, functions: &mut HashMap, TypedFunctionSymbol<'ast, T>>, - constants: &mut HashMap, TypedConstantSymbol<'ast, T>>, + constants: &mut HashMap, TypedConstantSymbol<'ast, T>>, symbol_unifier: &mut SymbolUnifier<'ast>, ) -> Result<(), Vec> { let mut errors: Vec = vec![]; @@ -506,7 +507,10 @@ impl<'ast, T: Field> Checker<'ast, T> { ), true => { constants.insert( - ConstantIdentifier::new(declaration.id, module_id.into()), + CanonicalConstantIdentifier::new( + declaration.id, + module_id.into(), + ), TypedConstantSymbol::Here(c.clone()), ); self.insert_into_scope(Variable::with_id_and_type( @@ -656,11 +660,11 @@ impl<'ast, T: Field> Checker<'ast, T> { }}); } true => { - let imported_id = ConstantIdentifier::new(import.symbol_id.into(), import.module_id); - let id = ConstantIdentifier::new(declaration.id.clone(), module_id.into()); + let imported_id = CanonicalConstantIdentifier::new(import.symbol_id, import.module_id); + let id = CanonicalConstantIdentifier::new(declaration.id, module_id.into()); constants.insert(id.clone(), TypedConstantSymbol::There(imported_id)); - self.insert_into_scope(Variable::with_id_and_type(declaration.id.clone(), ty.clone())); + self.insert_into_scope(Variable::with_id_and_type(declaration.id, ty.clone())); state .constants @@ -1144,7 +1148,7 @@ impl<'ast, T: Field> Checker<'ast, T> { match (constants_map.get(name), generics_map.get(&name)) { (Some(ty), None) => { match ty { - Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Identifier(name)), + Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Constant(name)), _ => Err(ErrorInner { pos: Some(pos), message: format!( diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 182c201f..788c2841 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -135,7 +135,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { println!("location {}", self.location.display()); match c { - DeclarationConstant::Identifier(id) => DeclarationConstant::Concrete( + DeclarationConstant::Constant(id) => DeclarationConstant::Concrete( match self .constants .get(&self.location) diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 3bdf36b8..af0f17d0 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -19,9 +19,10 @@ mod variable; pub use self::identifier::CoreIdentifier; pub use self::parameter::{DeclarationParameter, GParameter}; pub use self::types::{ - ConcreteFunctionKey, ConcreteSignature, ConcreteType, ConstantIdentifier, - DeclarationFunctionKey, DeclarationSignature, DeclarationType, GArrayType, GStructType, GType, - GenericIdentifier, IntoTypes, Signature, StructType, Type, Types, UBitwidth, + CanonicalConstantIdentifier, ConcreteFunctionKey, ConcreteSignature, ConcreteType, + ConstantIdentifier, DeclarationFunctionKey, DeclarationSignature, DeclarationType, GArrayType, + GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, Type, Types, + UBitwidth, }; use crate::typed_absy::types::ConcreteGenericsAssignment; @@ -65,12 +66,12 @@ pub type TypedFunctionSymbols<'ast, T> = #[derive(Clone, Debug, PartialEq)] pub enum TypedConstantSymbol<'ast, T> { Here(TypedConstant<'ast, T>), - There(ConstantIdentifier<'ast>), + There(CanonicalConstantIdentifier<'ast>), } /// A collection of `TypedConstantSymbol`s pub type TypedConstantSymbols<'ast, T> = - HashMap, TypedConstantSymbol<'ast, T>>; + HashMap, TypedConstantSymbol<'ast, T>>; /// A typed program as a collection of modules, one of them being the main #[derive(PartialEq, Debug, Clone)] diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 8a64927f..8ad4c91a 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -101,15 +101,17 @@ impl<'ast> fmt::Display for GenericIdentifier<'ast> { #[derive(Debug)] pub struct SpecializationError; +pub type ConstantIdentifier<'ast> = &'ast str; + #[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] -pub struct ConstantIdentifier<'ast> { +pub struct CanonicalConstantIdentifier<'ast> { pub module: OwnedTypedModuleId, - pub id: &'ast str, + pub id: ConstantIdentifier<'ast>, } -impl<'ast> ConstantIdentifier<'ast> { - pub fn new(id: &'ast str, module: OwnedTypedModuleId) -> Self { - ConstantIdentifier { id, module } +impl<'ast> CanonicalConstantIdentifier<'ast> { + pub fn new(id: ConstantIdentifier<'ast>, module: OwnedTypedModuleId) -> Self { + CanonicalConstantIdentifier { module, id } } } @@ -117,7 +119,7 @@ impl<'ast> ConstantIdentifier<'ast> { pub enum DeclarationConstant<'ast> { Generic(GenericIdentifier<'ast>), Concrete(u32), - Identifier(&'ast str), + Constant(ConstantIdentifier<'ast>), } impl<'ast> From for DeclarationConstant<'ast> { @@ -143,7 +145,7 @@ impl<'ast> fmt::Display for DeclarationConstant<'ast> { match self { DeclarationConstant::Generic(i) => write!(f, "{}", i), DeclarationConstant::Concrete(v) => write!(f, "{}", v), - DeclarationConstant::Identifier(v) => write!(f, "{}", v), + DeclarationConstant::Constant(v) => write!(f, "{}", v), } } } @@ -163,8 +165,9 @@ impl<'ast, T> From> for UExpression<'ast, T> { DeclarationConstant::Concrete(v) => { UExpressionInner::Value(v as u128).annotate(UBitwidth::B32) } - DeclarationConstant::Identifier(v) => UExpressionInner::Identifier(Identifier::from(v)) - .annotate(UBitwidth::from(UBitwidth::B32)), + DeclarationConstant::Constant(v) => { + UExpressionInner::Identifier(Identifier::from(v)).annotate(UBitwidth::B32) + } } } } @@ -991,7 +994,7 @@ pub mod signature { DeclarationConstant::Concrete(s0) => s1 == *s0 as usize, // in the case of a constant, we do not know the value yet, so we optimistically assume it's correct // if it does not match, it will be caught during inlining - DeclarationConstant::Identifier(..) => true, + DeclarationConstant::Constant(..) => true, } } (DeclarationType::FieldElement, GType::FieldElement) @@ -1017,7 +1020,7 @@ pub mod signature { let size = match t0.size { DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s), DeclarationConstant::Concrete(s) => Ok(s.into()), - DeclarationConstant::Identifier(..) => { + DeclarationConstant::Constant(..) => { unreachable!("identifiers should have been removed in constant inlining") } }?; From 5d6f29cb4ea4a52d42caf68ee34cc250ed0972b3 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 8 Jun 2021 16:56:29 +0200 Subject: [PATCH 06/14] make tests pass --- zokrates_core/src/semantics.rs | 6 +- .../src/static_analysis/constant_inliner.rs | 94 ++++++++++--------- zokrates_core/src/static_analysis/mod.rs | 2 +- zokrates_core/src/typed_absy/folder.rs | 5 +- zokrates_core/src/typed_absy/types.rs | 6 +- .../tests/tests/constants/import/origin.zok | 2 +- 6 files changed, 65 insertions(+), 50 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 37c4baeb..b7133bd8 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1122,7 +1122,8 @@ impl<'ast, T: Field> Checker<'ast, T> { fn check_generic_expression( &mut self, expr: ExpressionNode<'ast>, - constants_map: &HashMap<&'ast str, Type<'ast, T>>, + module_id: &ModuleId, + constants_map: &HashMap, Type<'ast, T>>, generics_map: &HashMap, usize>, ) -> Result, ErrorInner> { let pos = expr.pos(); @@ -1148,7 +1149,7 @@ impl<'ast, T: Field> Checker<'ast, T> { match (constants_map.get(name), generics_map.get(&name)) { (Some(ty), None) => { match ty { - Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Constant(name)), + Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Constant(CanonicalConstantIdentifier::new(name, module_id.into()))), _ => Err(ErrorInner { pos: Some(pos), message: format!( @@ -1192,6 +1193,7 @@ impl<'ast, T: Field> Checker<'ast, T> { UnresolvedType::Array(t, size) => { let checked_size = self.check_generic_expression( size.clone(), + module_id, state.constants.get(module_id).unwrap_or(&HashMap::new()), generics_map, )?; diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 788c2841..67c8a101 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -1,13 +1,14 @@ +use crate::static_analysis::Propagator; use crate::typed_absy::folder::*; +use crate::typed_absy::result_folder::ResultFolder; use crate::typed_absy::types::DeclarationConstant; use crate::typed_absy::*; -use core::str; use std::collections::HashMap; use std::convert::TryInto; use zokrates_field::Field; type ModuleConstants<'ast, T> = - HashMap>>; + HashMap, TypedExpression<'ast, T>>>; pub struct ConstantInliner<'ast, T> { modules: TypedModules<'ast, T>, @@ -43,7 +44,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { prev } - fn get_constant(&mut self, id: &Identifier) -> Option> { + fn get_constant(&mut self, id: &Identifier) -> Option> { assert_eq!(id.version, 0); match id.id { CoreIdentifier::Call(..) => { @@ -52,7 +53,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { CoreIdentifier::Source(id) => self .constants .get(&self.location) - .and_then(|constants| constants.get(id)) + .and_then(|constants| constants.get(&id.into())) .cloned(), } } @@ -85,29 +86,43 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { let constant = match tc { TypedConstantSymbol::There(imported_id) => { if !self.constants.contains_key(&imported_id.module) { - let current_m_id = self.change_location(id.module.clone()); - let _ = self - .fold_module(self.modules.get(&id.module).unwrap().clone()); + let current_m_id = + self.change_location(imported_id.module.clone()); + let _ = self.fold_module( + self.modules.get(&imported_id.module).unwrap().clone(), + ); self.change_location(current_m_id); } self.constants .get(&imported_id.module) .unwrap() - .get(&imported_id.id) + .get(&imported_id.id.into()) .cloned() .unwrap() } - TypedConstantSymbol::Here(c) => fold_constant(self, c), + TypedConstantSymbol::Here(c) => fold_constant(self, c).expression, }; + let constant = Propagator::with_constants( + self.constants.get_mut(&self.location).unwrap(), + ) + .fold_expression(constant) + .unwrap(); + assert!(self .constants .entry(self.location.clone()) .or_default() - .insert(id.id, constant.clone()) + .insert(id.id.into(), constant.clone()) .is_none()); - (id, TypedConstantSymbol::Here(constant)) + ( + id, + TypedConstantSymbol::Here(TypedConstant { + ty: constant.get_type().clone(), + expression: constant, + }), + ) }) .collect(), functions: m @@ -130,28 +145,20 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { &mut self, c: DeclarationConstant<'ast>, ) -> DeclarationConstant<'ast> { - println!("id {}", c); - println!("constants {:#?}", self.constants); - println!("location {}", self.location.display()); - match c { DeclarationConstant::Constant(id) => DeclarationConstant::Concrete( match self .constants - .get(&self.location) + .get(&id.module) .unwrap() - .get(&id) + .get(&id.id.into()) .cloned() .unwrap() { - TypedConstant { - ty: Type::Uint(UBitwidth::B32), - expression: - TypedExpression::Uint(UExpression { - inner: UExpressionInner::Value(v), - .. - }), - } => v as u32, + TypedExpression::Uint(UExpression { + inner: UExpressionInner::Value(v), + .. + }) => v as u32, _ => unreachable!(), }, ), @@ -165,7 +172,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { ) -> FieldElementExpression<'ast, T> { match e { FieldElementExpression::Identifier(ref id) => match self.get_constant(id) { - Some(c) => self.fold_constant(c).try_into().unwrap(), + Some(c) => self.fold_expression(c).try_into().unwrap(), None => fold_field_expression(self, e), }, e => fold_field_expression(self, e), @@ -178,7 +185,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { ) -> BooleanExpression<'ast, T> { match e { BooleanExpression::Identifier(ref id) => match self.get_constant(id) { - Some(c) => self.fold_constant(c).try_into().unwrap(), + Some(c) => self.fold_expression(c).try_into().unwrap(), None => fold_boolean_expression(self, e), }, e => fold_boolean_expression(self, e), @@ -193,7 +200,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { match e { UExpressionInner::Identifier(ref id) => match self.get_constant(id) { Some(c) => { - let e: UExpression<'ast, T> = self.fold_constant(c).try_into().unwrap(); + let e: UExpression<'ast, T> = self.fold_expression(c).try_into().unwrap(); e.into_inner() } None => fold_uint_expression_inner(self, size, e), @@ -210,7 +217,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { match e { ArrayExpressionInner::Identifier(ref id) => match self.get_constant(id) { Some(c) => { - let e: ArrayExpression<'ast, T> = self.fold_constant(c).try_into().unwrap(); + let e: ArrayExpression<'ast, T> = self.fold_expression(c).try_into().unwrap(); e.into_inner() } None => fold_array_expression_inner(self, ty, e), @@ -227,7 +234,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { match e { StructExpressionInner::Identifier(ref id) => match self.get_constant(id) { Some(c) => { - let e: StructExpression<'ast, T> = self.fold_constant(c).try_into().unwrap(); + let e: StructExpression<'ast, T> = self.fold_expression(c).try_into().unwrap(); e.into_inner() } None => fold_struct_expression_inner(self, ty, e), @@ -266,7 +273,7 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - const_id, + CanonicalConstantIdentifier::new(const_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number(Bn128Field::from(1))), @@ -354,7 +361,7 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - const_id, + CanonicalConstantIdentifier::new(const_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::Boolean, TypedExpression::Boolean(BooleanExpression::Value(true)), @@ -443,7 +450,7 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - const_id, + CanonicalConstantIdentifier::new(const_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::Uint(UBitwidth::B32), UExpressionInner::Value(1u128) @@ -544,7 +551,7 @@ mod tests { }; let constants: TypedConstantSymbols<_> = vec![( - const_id, + CanonicalConstantIdentifier::new(const_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::Array( @@ -683,7 +690,7 @@ mod tests { .collect(), constants: vec![ ( - const_a_id, + CanonicalConstantIdentifier::new(const_a_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( @@ -692,7 +699,7 @@ mod tests { )), ), ( - const_b_id, + CanonicalConstantIdentifier::new(const_b_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Add( @@ -741,7 +748,7 @@ mod tests { .collect(), constants: vec![ ( - const_a_id, + CanonicalConstantIdentifier::new(const_a_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( @@ -750,7 +757,7 @@ mod tests { )), ), ( - const_b_id, + CanonicalConstantIdentifier::new(const_b_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( @@ -802,7 +809,7 @@ mod tests { .into_iter() .collect(), constants: vec![( - foo_const_id, + CanonicalConstantIdentifier::new(foo_const_id, "foo".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( @@ -834,8 +841,11 @@ mod tests { .into_iter() .collect(), constants: vec![( - foo_const_id, - TypedConstantSymbol::There(OwnedTypedModuleId::from("foo"), foo_const_id), + CanonicalConstantIdentifier::new(foo_const_id, "main".into()), + TypedConstantSymbol::There(CanonicalConstantIdentifier::new( + foo_const_id, + "foo".into(), + )), )] .into_iter() .collect(), @@ -872,7 +882,7 @@ mod tests { .into_iter() .collect(), constants: vec![( - foo_const_id, + CanonicalConstantIdentifier::new(foo_const_id, "main".into()), TypedConstantSymbol::Here(TypedConstant::new( GType::FieldElement, TypedExpression::FieldElement(FieldElementExpression::Number( diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index 256f19fe..80670eca 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -78,13 +78,13 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> { // inline user-defined constants let r = ConstantInliner::inline(self); - println!("{}", r); // isolate branches let r = if config.isolate_branches { Isolator::isolate(r) } else { r }; + // reduce the program to a single function let r = reduce_program(r).map_err(Error::from)?; // generate abi diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index 2777bea0..22f3e229 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -1024,7 +1024,10 @@ pub fn fold_function_symbol<'ast, T: Field, F: Folder<'ast, T>>( ) -> TypedFunctionSymbol<'ast, T> { match s { TypedFunctionSymbol::Here(fun) => TypedFunctionSymbol::Here(f.fold_function(fun)), - there => there, // by default, do not fold modules recursively + TypedFunctionSymbol::There(key) => { + TypedFunctionSymbol::There(f.fold_declaration_function_key(key)) + } + s => s, } } diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 8ad4c91a..94794fcb 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -119,7 +119,7 @@ impl<'ast> CanonicalConstantIdentifier<'ast> { pub enum DeclarationConstant<'ast> { Generic(GenericIdentifier<'ast>), Concrete(u32), - Constant(ConstantIdentifier<'ast>), + Constant(CanonicalConstantIdentifier<'ast>), } impl<'ast> From for DeclarationConstant<'ast> { @@ -145,7 +145,7 @@ impl<'ast> fmt::Display for DeclarationConstant<'ast> { match self { DeclarationConstant::Generic(i) => write!(f, "{}", i), DeclarationConstant::Concrete(v) => write!(f, "{}", v), - DeclarationConstant::Constant(v) => write!(f, "{}", v), + DeclarationConstant::Constant(v) => write!(f, "{}/{}", v.module.display(), v.id), } } } @@ -166,7 +166,7 @@ impl<'ast, T> From> for UExpression<'ast, T> { UExpressionInner::Value(v as u128).annotate(UBitwidth::B32) } DeclarationConstant::Constant(v) => { - UExpressionInner::Identifier(Identifier::from(v)).annotate(UBitwidth::B32) + UExpressionInner::Identifier(Identifier::from(v.id)).annotate(UBitwidth::B32) } } } diff --git a/zokrates_core_test/tests/tests/constants/import/origin.zok b/zokrates_core_test/tests/tests/constants/import/origin.zok index e48514af..297e1ac4 100644 --- a/zokrates_core_test/tests/tests/constants/import/origin.zok +++ b/zokrates_core_test/tests/tests/constants/import/origin.zok @@ -1,3 +1,3 @@ -const u32 N = 1 +const u32 N = 1 + 1 def foo(field[N] a) -> bool: return true \ No newline at end of file From 33f0db4d47581f258dc015d86cfffceabd5f66c4 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 8 Jun 2021 16:58:38 +0200 Subject: [PATCH 07/14] changelog --- changelogs/unreleased/913-schaeff | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/913-schaeff diff --git a/changelogs/unreleased/913-schaeff b/changelogs/unreleased/913-schaeff new file mode 100644 index 00000000..5e0710d4 --- /dev/null +++ b/changelogs/unreleased/913-schaeff @@ -0,0 +1 @@ +Fix crash on import of functions containing constants \ No newline at end of file From 09c86e1735c75886e57ffac1a11696113e19637a Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 11 Jun 2021 12:04:38 +0200 Subject: [PATCH 08/14] keep constants ordered for inlining, clean --- zokrates_core/src/semantics.rs | 14 +- .../src/static_analysis/constant_inliner.rs | 135 +++++++++--------- zokrates_core/src/typed_absy/mod.rs | 7 +- 3 files changed, 81 insertions(+), 75 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index b7133bd8..dfa75dfc 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -445,8 +445,8 @@ impl<'ast, T: Field> Checker<'ast, T> { declaration: SymbolDeclarationNode<'ast>, module_id: &ModuleId, state: &mut State<'ast, T>, - functions: &mut HashMap, TypedFunctionSymbol<'ast, T>>, - constants: &mut HashMap, TypedConstantSymbol<'ast, T>>, + functions: &mut TypedFunctionSymbols<'ast, T>, + constants: &mut TypedConstantSymbols<'ast, T>, symbol_unifier: &mut SymbolUnifier<'ast>, ) -> Result<(), Vec> { let mut errors: Vec = vec![]; @@ -506,13 +506,13 @@ impl<'ast, T: Field> Checker<'ast, T> { .in_file(module_id), ), true => { - constants.insert( + constants.push(( CanonicalConstantIdentifier::new( declaration.id, module_id.into(), ), TypedConstantSymbol::Here(c.clone()), - ); + )); self.insert_into_scope(Variable::with_id_and_type( declaration.id, c.get_type(), @@ -663,7 +663,7 @@ impl<'ast, T: Field> Checker<'ast, T> { let imported_id = CanonicalConstantIdentifier::new(import.symbol_id, import.module_id); let id = CanonicalConstantIdentifier::new(declaration.id, module_id.into()); - constants.insert(id.clone(), TypedConstantSymbol::There(imported_id)); + constants.push((id.clone(), TypedConstantSymbol::There(imported_id))); self.insert_into_scope(Variable::with_id_and_type(declaration.id, ty.clone())); state @@ -760,8 +760,8 @@ impl<'ast, T: Field> Checker<'ast, T> { module_id: &ModuleId, state: &mut State<'ast, T>, ) -> Result<(), Vec> { - let mut checked_functions = HashMap::new(); - let mut checked_constants = HashMap::new(); + let mut checked_functions = TypedFunctionSymbols::new(); + let mut checked_constants = TypedConstantSymbols::new(); // check if the module was already removed from the untyped ones let to_insert = match state.modules.remove(module_id) { diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 67c8a101..28ea448a 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -34,16 +34,16 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { inliner.fold_program(p) } - // fn module(&self) -> &TypedModule<'ast, T> { - // self.modules.get(&self.location).unwrap() - // } - fn change_location(&mut self, location: OwnedTypedModuleId) -> OwnedTypedModuleId { let prev = self.location.clone(); self.location = location; prev } + fn treated(&self, id: &OwnedTypedModuleId) -> bool { + self.constants.contains_key(id) + } + fn get_constant(&mut self, id: &Identifier) -> Option> { assert_eq!(id.version, 0); match id.id { @@ -66,8 +66,12 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { .modules .into_iter() .map(|(m_id, m)| { - self.change_location(m_id.clone()); - (m_id, self.fold_module(m)) + if !self.treated(&m_id) { + self.change_location(m_id.clone()); + (m_id, self.fold_module(m)) + } else { + (m_id, m) + } }) .collect(), ..p @@ -75,69 +79,68 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { } fn fold_module(&mut self, m: TypedModule<'ast, T>) -> TypedModule<'ast, T> { - // only treat this module if its constants are not in the map yet - if !self.constants.contains_key(&self.location) { - self.constants.entry(self.location.clone()).or_default(); - TypedModule { - constants: m - .constants - .into_iter() - .map(|(id, tc)| { - let constant = match tc { - TypedConstantSymbol::There(imported_id) => { - if !self.constants.contains_key(&imported_id.module) { - let current_m_id = - self.change_location(imported_id.module.clone()); - let _ = self.fold_module( - self.modules.get(&imported_id.module).unwrap().clone(), - ); - self.change_location(current_m_id); - } - self.constants - .get(&imported_id.module) - .unwrap() - .get(&imported_id.id.into()) - .cloned() - .unwrap() + assert!(self + .constants + .insert(self.location.clone(), Default::default()) + .is_none()); + TypedModule { + constants: m + .constants + .into_iter() + .map(|(id, tc)| { + let constant = match tc { + TypedConstantSymbol::There(imported_id) => { + if !self.treated(&imported_id.module) { + let current_m_id = self.change_location(imported_id.module.clone()); + let m = self.fold_module( + self.modules.get(&imported_id.module).unwrap().clone(), + ); + + self.modules.insert(imported_id.module.clone(), m); + + self.change_location(current_m_id); } - TypedConstantSymbol::Here(c) => fold_constant(self, c).expression, - }; + self.constants + .get(&imported_id.module) + .unwrap() + .get(&imported_id.id.into()) + .cloned() + .unwrap() + } + TypedConstantSymbol::Here(c) => fold_constant(self, c).expression, + }; - let constant = Propagator::with_constants( - self.constants.get_mut(&self.location).unwrap(), - ) - .fold_expression(constant) - .unwrap(); + let constant = + Propagator::with_constants(self.constants.get_mut(&self.location).unwrap()) + .fold_expression(constant) + .unwrap(); - assert!(self - .constants - .entry(self.location.clone()) - .or_default() - .insert(id.id.into(), constant.clone()) - .is_none()); + assert!(self + .constants + .entry(self.location.clone()) + .or_default() + .insert(id.id.into(), constant.clone()) + .is_none()); - ( - id, - TypedConstantSymbol::Here(TypedConstant { - ty: constant.get_type().clone(), - expression: constant, - }), - ) - }) - .collect(), - functions: m - .functions - .into_iter() - .map(|(key, fun)| { - ( - self.fold_declaration_function_key(key), - self.fold_function_symbol(fun), - ) - }) - .collect(), - } - } else { - m + ( + id, + TypedConstantSymbol::Here(TypedConstant { + ty: constant.get_type().clone(), + expression: constant, + }), + ) + }) + .collect(), + functions: m + .functions + .into_iter() + .map(|(key, fun)| { + ( + self.fold_declaration_function_key(key), + self.fold_function_symbol(fun), + ) + }) + .collect(), } } @@ -159,7 +162,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { inner: UExpressionInner::Value(v), .. }) => v as u32, - _ => unreachable!(), + _ => unreachable!("all constants should be reduceable to u32 literals"), }, ), c => c, diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index af0f17d0..0e5e5486 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -70,8 +70,11 @@ pub enum TypedConstantSymbol<'ast, T> { } /// A collection of `TypedConstantSymbol`s -pub type TypedConstantSymbols<'ast, T> = - HashMap, TypedConstantSymbol<'ast, T>>; +/// It is still ordered, as we inline the constants in the order they are declared +pub type TypedConstantSymbols<'ast, T> = Vec<( + CanonicalConstantIdentifier<'ast>, + TypedConstantSymbol<'ast, T>, +)>; /// A typed program as a collection of modules, one of them being the main #[derive(PartialEq, Debug, Clone)] From 0bb9f5897a1f96fbf581eaebf6d6837e270a0c7a Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 11 Jun 2021 12:11:52 +0200 Subject: [PATCH 09/14] clippy --- zokrates_core/src/static_analysis/constant_inliner.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 28ea448a..634bcef5 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -40,7 +40,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { prev } - fn treated(&self, id: &OwnedTypedModuleId) -> bool { + fn treated(&self, id: &TypedModuleId) -> bool { self.constants.contains_key(id) } @@ -149,6 +149,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { c: DeclarationConstant<'ast>, ) -> DeclarationConstant<'ast> { match c { + // replace constants by their concrete value in declaration types DeclarationConstant::Constant(id) => DeclarationConstant::Concrete( match self .constants From 5c3bd450ed552b09dfdebaa380d668ee247d24a2 Mon Sep 17 00:00:00 2001 From: dark64 Date: Fri, 11 Jun 2021 13:21:12 +0200 Subject: [PATCH 10/14] update blake2 tests --- .../tests/tests/hashes/blake2/blake2s_1024bit.zok | 10 +++++----- .../tests/tests/hashes/blake2/blake2s_1536bit.zok | 10 +++++----- .../tests/tests/hashes/blake2/blake2s_512bit.zok | 10 +++++----- .../tests/tests/hashes/blake2/blake2s_8192bit.zok | 10 +++++----- .../tests/tests/hashes/blake2/blake2s_p.zok | 10 +++++----- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok index 55beccfb..28290d22 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.zok @@ -4,14 +4,14 @@ import "hashes/blake2/blake2s" // >>> from hashlib import blake2s // >>> digest = blake2s() -// >>> digest.update(b'\x00' * 128) +// >>> digest.update(b'\x12\x34\x56\x78' * 32) // >>> digest.hexdigest() -// '4e420520b981ce7bdbf4ce2c4dbadb9450079b7deb9737b5232957d323f801cb' +// '4858b8174f8f5851ddac0507003b2490f42c33df8362770c5e79b770c84ffdb4' def main(): - u32[8] h = blake2s::<2>([[0; 16]; 2]) // 2 * 16 * 32 = 1024 bit input + u32[8] h = blake2s::<2>([[0x12345678; 16]; 2]) // 2 * 16 * 32 = 1024 bit input assert(h == [ - 0x4E420520, 0xB981CE7B, 0xDBF4CE2C, 0x4DBADB94, - 0x50079B7D, 0xEB9737B5, 0x232957D3, 0x23F801CB + 0x4858B817, 0x4F8F5851, 0xDDAC0507, 0x003B2490, + 0xF42C33DF, 0x8362770C, 0x5E79B770, 0xC84FFDB4 ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok index 61dc35d4..05340e3c 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.zok @@ -4,14 +4,14 @@ import "hashes/blake2/blake2s" // >>> from hashlib import blake2s // >>> digest = blake2s() -// >>> digest.update(b'\x00\x00\x00\x2A' * 48) +// >>> digest.update(b'\x12\x34\x56\x78' * 48) // >>> digest.hexdigest() -// '2707edbde466a6632371e0611804ecdbe3e21dd683ce9d2060c50341b6fa99ed' +// '879043503b04cab2f3c0d7a4bb01c1db74c238c49887da84e8a619893092b6e2' def main(): - u32[8] h = blake2s::<3>([[42; 16]; 3]) // 3 * 16 * 32 = 1536 bit input + u32[8] h = blake2s::<3>([[0x12345678; 16]; 3]) // 3 * 16 * 32 = 1536 bit input assert(h == [ - 0x2707EDBD, 0xE466A663, 0x2371E061, 0x1804ECDB, - 0xE3E21DD6, 0x83CE9D20, 0x60C50341, 0xB6FA99ED + 0x87904350, 0x3B04CAB2, 0xF3C0D7A4, 0xBB01C1DB, + 0x74C238C4, 0x9887DA84, 0xE8A61989, 0x3092B6E2 ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok index 2971542a..2398c608 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.zok @@ -4,14 +4,14 @@ import "hashes/blake2/blake2s" // >>> from hashlib import blake2s // >>> digest = blake2s() -// >>> digest.update(b'\x00' * 64) +// >>> digest.update(b'\x12\x34\x56\x78' * 16) // >>> digest.hexdigest() -// 'ae09db7cd54f42b490ef09b6bc541af688e4959bb8c53f359a6f56e38ab454a3' +// '52af1aec3e6663bcc759d55fc7557fbb2f710219f0de138b1b52c919f5c94415' def main(): - u32[8] h = blake2s::<1>([[0; 16]; 1]) // 16 * 32 = 512 bit input + u32[8] h = blake2s::<1>([[0x12345678; 16]; 1]) // 16 * 32 = 512 bit input assert(h == [ - 0xAE09DB7C, 0xD54F42B4, 0x90EF09B6, 0xBC541AF6, - 0x88E4959B, 0xB8C53F35, 0x9A6F56E3, 0x8AB454A3 + 0x52AF1AEC, 0x3E6663BC, 0xC759D55F, 0xC7557FBB, + 0x2F710219, 0xF0DE138B, 0x1B52C919, 0xF5C94415 ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok index 8d860131..6da46703 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.zok @@ -4,14 +4,14 @@ import "hashes/blake2/blake2s" // >>> from hashlib import blake2s // >>> digest = blake2s() -// >>> digest.update(b'\x00' * 1024) +// >>> digest.update(b'\x12\x34\x56\x78' * 256) // >>> digest.hexdigest() -// '035366632a506c045d4a51c833e8b76791d5daa9bca821b4a2732a66fb5aa22d' +// 'b41c4704f49df139039bbc91c6e23a84198ffedc78d0b677e8b2a6a57f3460e8' def main(): - u32[8] h = blake2s::<16>([[0; 16]; 16]) // 16 * 16 * 32 = 8192 bit input + u32[8] h = blake2s::<16>([[0x12345678; 16]; 16]) // 16 * 16 * 32 = 8192 bit input assert(h == [ - 0x03536663, 0x2A506C04, 0x5D4A51C8, 0x33E8B767, - 0x91D5DAA9, 0xBCA821B4, 0xA2732A66, 0xFB5AA22D + 0xB41C4704, 0xF49DF139, 0x039BBC91, 0xC6E23A84, + 0x198FFEDC, 0x78D0B677, 0xE8B2A6A5, 0x7F3460E8 ]) return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok index 3e83026e..ecea1f26 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.zok @@ -4,14 +4,14 @@ import "hashes/blake2/blake2s_p" as blake2s // >>> from hashlib import blake2s // >>> digest = blake2s(person=b'\x12\x34\x56\x78\x00\x00\x00\x00') -// >>> digest.update(b'\x00' * 64) +// >>> digest.update(b'\x12\x34\x56\x78' * 16) // >>> digest.hexdigest() -// 'a6e927d1b9d50453bc6eb5e4050c443a7203a541cc06ba78a7dc00caa69fb3e9' +// '780105bc9ca7633b1f289b3d1558dece65e04ac23f88e711dc29600fa3e0258a' def main(): - u32[8] h = blake2s::<1>([[0; 16]; 1], [0x12345678, 0]) + u32[8] h = blake2s::<1>([[0x12345678; 16]; 1], [0x12345678, 0]) assert(h == [ - 0xA6E927D1, 0xB9D50453, 0xBC6EB5E4, 0x050C443A, - 0x7203A541, 0xCC06BA78, 0xA7DC00CA, 0xA69FB3E9 + 0x780105BC, 0x9CA7633B, 0x1F289B3D, 0x1558DECE, + 0x65E04AC2, 0x3F88E711, 0xDC29600F, 0xA3E0258A ]) return \ No newline at end of file From 759f4dd5534b779c0d73172a94a91ce63ccaac48 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 15 Jun 2021 16:41:38 +0200 Subject: [PATCH 11/14] fold module id in folders --- access.zok | 2 + .../examples/imports/import_with_alias.zok | 4 +- .../src/static_analysis/constant_inliner.rs | 56 +++++++------------ zokrates_core/src/typed_absy/folder.rs | 29 ++++++++-- zokrates_core/src/typed_absy/result_folder.rs | 26 ++++++++- 5 files changed, 73 insertions(+), 44 deletions(-) create mode 100644 access.zok diff --git a/access.zok b/access.zok new file mode 100644 index 00000000..7d01f505 --- /dev/null +++ b/access.zok @@ -0,0 +1,2 @@ +def main(field[3][2] a, u32 index) -> field[2]: + return a[index] \ No newline at end of file diff --git a/zokrates_cli/examples/imports/import_with_alias.zok b/zokrates_cli/examples/imports/import_with_alias.zok index 5e013691..7302c4e2 100644 --- a/zokrates_cli/examples/imports/import_with_alias.zok +++ b/zokrates_cli/examples/imports/import_with_alias.zok @@ -1,8 +1,8 @@ -from "./bar" import main as bar +//from "./bar" import main as bar from "./baz" import BAZ as baz import "./foo" as f def main() -> field: field foo = f() - assert(foo == bar() + baz) + assert(foo == 21 + baz) return foo \ No newline at end of file diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index 634bcef5..e92bd259 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -48,7 +48,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { assert_eq!(id.version, 0); match id.id { CoreIdentifier::Call(..) => { - unreachable!("calls indentifiers are only available after call inlining") + unreachable!("calls identifiers are only available after call inlining") } CoreIdentifier::Source(id) => self .constants @@ -60,46 +60,34 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { } impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { - fn fold_program(&mut self, p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { - TypedProgram { - modules: p - .modules - .into_iter() - .map(|(m_id, m)| { - if !self.treated(&m_id) { - self.change_location(m_id.clone()); - (m_id, self.fold_module(m)) - } else { - (m_id, m) - } - }) - .collect(), - ..p + fn fold_module_id(&mut self, id: OwnedTypedModuleId) -> OwnedTypedModuleId { + // anytime we encounter a module id, visit the corresponding module if it hasn't been done yet + if !self.treated(&id) { + let current_m_id = self.change_location(id.clone()); + self.constants.entry(self.location.clone()).or_default(); + let m = self.fold_module(self.modules.get(&id).unwrap().clone()); + + self.modules.insert(id.clone(), m); + + self.change_location(current_m_id); } + id } fn fold_module(&mut self, m: TypedModule<'ast, T>) -> TypedModule<'ast, T> { - assert!(self - .constants - .insert(self.location.clone(), Default::default()) - .is_none()); + // initialise a constant map for this module + self.constants.entry(self.location.clone()).or_default(); + TypedModule { constants: m .constants .into_iter() .map(|(id, tc)| { + let id = self.fold_canonical_constant_identifier(id); + let constant = match tc { TypedConstantSymbol::There(imported_id) => { - if !self.treated(&imported_id.module) { - let current_m_id = self.change_location(imported_id.module.clone()); - let m = self.fold_module( - self.modules.get(&imported_id.module).unwrap().clone(), - ); - - self.modules.insert(imported_id.module.clone(), m); - - self.change_location(current_m_id); - } + let imported_id = self.fold_canonical_constant_identifier(imported_id); self.constants .get(&imported_id.module) .unwrap() @@ -115,12 +103,10 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { .fold_expression(constant) .unwrap(); - assert!(self - .constants + self.constants .entry(self.location.clone()) .or_default() - .insert(id.id.into(), constant.clone()) - .is_none()); + .insert(id.id.into(), constant.clone()); ( id, @@ -176,7 +162,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { ) -> FieldElementExpression<'ast, T> { match e { FieldElementExpression::Identifier(ref id) => match self.get_constant(id) { - Some(c) => self.fold_expression(c).try_into().unwrap(), + Some(c) => c.try_into().unwrap(), None => fold_field_expression(self, e), }, e => fold_field_expression(self, e), diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index 22f3e229..41a39706 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -215,6 +215,20 @@ pub trait Folder<'ast, T: Field>: Sized { } } + fn fold_canonical_constant_identifier( + &mut self, + i: CanonicalConstantIdentifier<'ast>, + ) -> CanonicalConstantIdentifier<'ast> { + CanonicalConstantIdentifier { + module: self.fold_module_id(i.module), + id: i.id, + } + } + + fn fold_module_id(&mut self, i: OwnedTypedModuleId) -> OwnedTypedModuleId { + i + } + fn fold_expression(&mut self, e: TypedExpression<'ast, T>) -> TypedExpression<'ast, T> { match e { TypedExpression::FieldElement(e) => self.fold_field_expression(e).into(), @@ -342,7 +356,12 @@ pub fn fold_module<'ast, T: Field, F: Folder<'ast, T>>( constants: m .constants .into_iter() - .map(|(key, tc)| (key, f.fold_constant_symbol(tc))) + .map(|(id, tc)| { + ( + f.fold_canonical_constant_identifier(id), + f.fold_constant_symbol(tc), + ) + }) .collect(), functions: m .functions @@ -1014,7 +1033,9 @@ pub fn fold_constant_symbol<'ast, T: Field, F: Folder<'ast, T>>( ) -> TypedConstantSymbol<'ast, T> { match s { TypedConstantSymbol::Here(tc) => TypedConstantSymbol::Here(f.fold_constant(tc)), - there => there, + TypedConstantSymbol::There(id) => { + TypedConstantSymbol::There(f.fold_canonical_constant_identifier(id)) + } } } @@ -1052,8 +1073,8 @@ pub fn fold_program<'ast, T: Field, F: Folder<'ast, T>>( modules: p .modules .into_iter() - .map(|(module_id, module)| (module_id, f.fold_module(module))) + .map(|(module_id, module)| (f.fold_module_id(module_id), f.fold_module(module))) .collect(), - main: p.main, + main: f.fold_module_id(p.main), } } diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_core/src/typed_absy/result_folder.rs index cbca2f7e..b78e81a2 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_core/src/typed_absy/result_folder.rs @@ -114,6 +114,20 @@ pub trait ResultFolder<'ast, T: Field>: Sized { }) } + fn fold_canonical_constant_identifier( + &mut self, + i: CanonicalConstantIdentifier<'ast>, + ) -> Result, Self::Error> { + Ok(CanonicalConstantIdentifier { + module: self.fold_module_id(i.module)?, + id: i.id, + }) + } + + fn fold_module_id(&mut self, i: OwnedTypedModuleId) -> Result { + Ok(i) + } + fn fold_name(&mut self, n: Identifier<'ast>) -> Result, Self::Error> { Ok(n) } @@ -923,6 +937,7 @@ pub fn fold_declaration_function_key<'ast, T: Field, F: ResultFolder<'ast, T>>( key: DeclarationFunctionKey<'ast>, ) -> Result, F::Error> { Ok(DeclarationFunctionKey { + module: f.fold_module_id(key.module)?, signature: f.fold_signature(key.signature)?, ..key }) @@ -1067,7 +1082,9 @@ pub fn fold_constant_symbol<'ast, T: Field, F: ResultFolder<'ast, T>>( ) -> Result, F::Error> { match s { TypedConstantSymbol::Here(tc) => Ok(TypedConstantSymbol::Here(f.fold_constant(tc)?)), - there => Ok(there), + TypedConstantSymbol::There(id) => Ok(TypedConstantSymbol::There( + f.fold_canonical_constant_identifier(id)?, + )), } } @@ -1077,7 +1094,10 @@ pub fn fold_function_symbol<'ast, T: Field, F: ResultFolder<'ast, T>>( ) -> Result, F::Error> { match s { TypedFunctionSymbol::Here(fun) => Ok(TypedFunctionSymbol::Here(f.fold_function(fun)?)), - there => Ok(there), // by default, do not fold modules recursively + TypedFunctionSymbol::There(key) => Ok(TypedFunctionSymbol::There( + f.fold_declaration_function_key(key)?, + )), + s => Ok(s), } } @@ -1109,6 +1129,6 @@ pub fn fold_program<'ast, T: Field, F: ResultFolder<'ast, T>>( .into_iter() .map(|(module_id, module)| f.fold_module(module).map(|m| (module_id, m))) .collect::>()?, - main: p.main, + main: f.fold_module_id(p.main)?, }) } From 59023ca67780132c16f73c7860d2d8a1b8694b8a Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 16 Jun 2021 16:25:01 +0200 Subject: [PATCH 12/14] refactor for clarity, clean --- zokrates_cli/examples/imports/import_with_alias.zok | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zokrates_cli/examples/imports/import_with_alias.zok b/zokrates_cli/examples/imports/import_with_alias.zok index 7302c4e2..5e013691 100644 --- a/zokrates_cli/examples/imports/import_with_alias.zok +++ b/zokrates_cli/examples/imports/import_with_alias.zok @@ -1,8 +1,8 @@ -//from "./bar" import main as bar +from "./bar" import main as bar from "./baz" import BAZ as baz import "./foo" as f def main() -> field: field foo = f() - assert(foo == 21 + baz) + assert(foo == bar() + baz) return foo \ No newline at end of file From 6b4a80d8917bc61c3dc4b31d781bf4302e1db47c Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 16 Jun 2021 16:30:46 +0200 Subject: [PATCH 13/14] clean --- access.zok | 2 - .../src/static_analysis/constant_inliner.rs | 129 +++++++++--------- zokrates_core/src/typed_absy/mod.rs | 2 + 3 files changed, 66 insertions(+), 67 deletions(-) delete mode 100644 access.zok diff --git a/access.zok b/access.zok deleted file mode 100644 index 7d01f505..00000000 --- a/access.zok +++ /dev/null @@ -1,2 +0,0 @@ -def main(field[3][2] a, u32 index) -> field[2]: - return a[index] \ No newline at end of file diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index e92bd259..a0408729 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -7,20 +7,20 @@ use std::collections::HashMap; use std::convert::TryInto; use zokrates_field::Field; -type ModuleConstants<'ast, T> = +type ProgramConstants<'ast, T> = HashMap, TypedExpression<'ast, T>>>; pub struct ConstantInliner<'ast, T> { modules: TypedModules<'ast, T>, location: OwnedTypedModuleId, - constants: ModuleConstants<'ast, T>, + constants: ProgramConstants<'ast, T>, } impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { pub fn new( modules: TypedModules<'ast, T>, location: OwnedTypedModuleId, - constants: ModuleConstants<'ast, T>, + constants: ProgramConstants<'ast, T>, ) -> Self { ConstantInliner { modules, @@ -29,7 +29,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { } } pub fn inline(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> { - let constants = HashMap::new(); + let constants = ProgramConstants::new(); let mut inliner = ConstantInliner::new(p.modules.clone(), p.main.clone(), constants); inliner.fold_program(p) } @@ -37,6 +37,7 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { fn change_location(&mut self, location: OwnedTypedModuleId) -> OwnedTypedModuleId { let prev = self.location.clone(); self.location = location; + self.constants.entry(self.location.clone()).or_default(); prev } @@ -44,18 +45,24 @@ impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> { self.constants.contains_key(id) } - fn get_constant(&mut self, id: &Identifier) -> Option> { - assert_eq!(id.version, 0); - match id.id { - CoreIdentifier::Call(..) => { - unreachable!("calls identifiers are only available after call inlining") - } - CoreIdentifier::Source(id) => self - .constants - .get(&self.location) - .and_then(|constants| constants.get(&id.into())) - .cloned(), - } + fn get_constant( + &self, + id: &CanonicalConstantIdentifier<'ast>, + ) -> Option> { + self.constants + .get(&id.module) + .and_then(|constants| constants.get(&id.id.into())) + .cloned() + } + + fn get_constant_for_identifier( + &self, + id: &Identifier<'ast>, + ) -> Option> { + self.constants + .get(&self.location) + .and_then(|constants| constants.get(&id)) + .cloned() } } @@ -64,48 +71,42 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { // anytime we encounter a module id, visit the corresponding module if it hasn't been done yet if !self.treated(&id) { let current_m_id = self.change_location(id.clone()); - self.constants.entry(self.location.clone()).or_default(); - let m = self.fold_module(self.modules.get(&id).unwrap().clone()); - + let m = self.modules.remove(&id).unwrap(); + let m = self.fold_module(m); self.modules.insert(id.clone(), m); - self.change_location(current_m_id); } id } fn fold_module(&mut self, m: TypedModule<'ast, T>) -> TypedModule<'ast, T> { - // initialise a constant map for this module - self.constants.entry(self.location.clone()).or_default(); - TypedModule { constants: m .constants .into_iter() .map(|(id, tc)| { - let id = self.fold_canonical_constant_identifier(id); - let constant = match tc { TypedConstantSymbol::There(imported_id) => { + // visit the imported symbol. This triggers visiting the corresponding module if needed let imported_id = self.fold_canonical_constant_identifier(imported_id); - self.constants - .get(&imported_id.module) - .unwrap() - .get(&imported_id.id.into()) - .cloned() + // after that, the constant must have been defined defined in the global map. It is already reduced + // to a literal, so running propagation isn't required + self.get_constant(&imported_id).unwrap() + } + TypedConstantSymbol::Here(c) => { + let non_propagated_constant = fold_constant(self, c).expression; + // folding the constant above only reduces it to an expression containing only literals, not to a single literal. + // propagating with an empty map of constants reduces it to a single literal + Propagator::with_constants(&mut HashMap::default()) + .fold_expression(non_propagated_constant) .unwrap() } - TypedConstantSymbol::Here(c) => fold_constant(self, c).expression, }; - let constant = - Propagator::with_constants(self.constants.get_mut(&self.location).unwrap()) - .fold_expression(constant) - .unwrap(); - + // add to the constant map. The value added is always a single litteral self.constants - .entry(self.location.clone()) - .or_default() + .get_mut(&self.location) + .unwrap() .insert(id.id.into(), constant.clone()); ( @@ -136,22 +137,15 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { ) -> DeclarationConstant<'ast> { match c { // replace constants by their concrete value in declaration types - DeclarationConstant::Constant(id) => DeclarationConstant::Concrete( - match self - .constants - .get(&id.module) - .unwrap() - .get(&id.id.into()) - .cloned() - .unwrap() - { + DeclarationConstant::Constant(id) => { + DeclarationConstant::Concrete(match self.get_constant(&id).unwrap() { TypedExpression::Uint(UExpression { inner: UExpressionInner::Value(v), .. }) => v as u32, _ => unreachable!("all constants should be reduceable to u32 literals"), - }, - ), + }) + } c => c, } } @@ -161,10 +155,12 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { e: FieldElementExpression<'ast, T>, ) -> FieldElementExpression<'ast, T> { match e { - FieldElementExpression::Identifier(ref id) => match self.get_constant(id) { - Some(c) => c.try_into().unwrap(), - None => fold_field_expression(self, e), - }, + FieldElementExpression::Identifier(ref id) => { + match self.get_constant_for_identifier(id) { + Some(c) => c.try_into().unwrap(), + None => fold_field_expression(self, e), + } + } e => fold_field_expression(self, e), } } @@ -174,8 +170,8 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { e: BooleanExpression<'ast, T>, ) -> BooleanExpression<'ast, T> { match e { - BooleanExpression::Identifier(ref id) => match self.get_constant(id) { - Some(c) => self.fold_expression(c).try_into().unwrap(), + BooleanExpression::Identifier(ref id) => match self.get_constant_for_identifier(id) { + Some(c) => c.try_into().unwrap(), None => fold_boolean_expression(self, e), }, e => fold_boolean_expression(self, e), @@ -188,9 +184,9 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { e: UExpressionInner<'ast, T>, ) -> UExpressionInner<'ast, T> { match e { - UExpressionInner::Identifier(ref id) => match self.get_constant(id) { + UExpressionInner::Identifier(ref id) => match self.get_constant_for_identifier(id) { Some(c) => { - let e: UExpression<'ast, T> = self.fold_expression(c).try_into().unwrap(); + let e: UExpression<'ast, T> = c.try_into().unwrap(); e.into_inner() } None => fold_uint_expression_inner(self, size, e), @@ -205,13 +201,15 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { e: ArrayExpressionInner<'ast, T>, ) -> ArrayExpressionInner<'ast, T> { match e { - ArrayExpressionInner::Identifier(ref id) => match self.get_constant(id) { - Some(c) => { - let e: ArrayExpression<'ast, T> = self.fold_expression(c).try_into().unwrap(); - e.into_inner() + ArrayExpressionInner::Identifier(ref id) => { + match self.get_constant_for_identifier(id) { + Some(c) => { + let e: ArrayExpression<'ast, T> = c.try_into().unwrap(); + e.into_inner() + } + None => fold_array_expression_inner(self, ty, e), } - None => fold_array_expression_inner(self, ty, e), - }, + } e => fold_array_expression_inner(self, ty, e), } } @@ -222,9 +220,10 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { - StructExpressionInner::Identifier(ref id) => match self.get_constant(id) { + StructExpressionInner::Identifier(ref id) => match self.get_constant_for_identifier(id) + { Some(c) => { - let e: StructExpression<'ast, T> = self.fold_expression(c).try_into().unwrap(); + let e: StructExpression<'ast, T> = c.try_into().unwrap(); e.into_inner() } None => fold_struct_expression_inner(self, ty, e), diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 0e5e5486..61012739 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -298,6 +298,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> { #[derive(Clone, PartialEq, Debug)] pub struct TypedConstant<'ast, T> { + // the type is already stored in the TypedExpression, but we want to avoid awkward trait bounds in `fmt::Display` pub ty: Type<'ast, T>, pub expression: TypedExpression<'ast, T>, } @@ -310,6 +311,7 @@ impl<'ast, T> TypedConstant<'ast, T> { impl<'ast, T: fmt::Display> fmt::Display for TypedConstant<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // using `self.expression.get_type()` would be better here but ends up requiring stronger trait bounds write!(f, "const {}({})", self.ty, self.expression) } } From 9e99cc19c77bfb0ca3a89483d6ec8c9985f51b96 Mon Sep 17 00:00:00 2001 From: schaeff Date: Wed, 16 Jun 2021 16:36:44 +0200 Subject: [PATCH 14/14] adjust panic message --- zokrates_core/src/static_analysis/constant_inliner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zokrates_core/src/static_analysis/constant_inliner.rs b/zokrates_core/src/static_analysis/constant_inliner.rs index a0408729..25d119db 100644 --- a/zokrates_core/src/static_analysis/constant_inliner.rs +++ b/zokrates_core/src/static_analysis/constant_inliner.rs @@ -143,7 +143,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> { inner: UExpressionInner::Value(v), .. }) => v as u32, - _ => unreachable!("all constants should be reduceable to u32 literals"), + _ => unreachable!("all constants found in declaration types should be reduceable to u32 literals"), }) } c => c,