From 14b09d8878ea6a8b704a9472135ca22accc7bd10 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 13 Dec 2024 10:57:40 -0700 Subject: [PATCH] cleanup --- ...ha20_nivc.circom => authentication.circom} | 20 +- ...20-nivc.test.ts => authentication.test.ts} | 21 +- circuits/test/chacha20/chacha20.test.ts | 131 ++++---- circuits/test/full/full.test.ts | 34 +- circuits/test/http/verification.test.ts | 3 +- circuits/test/json/extraction.test.ts | 4 - circuits/test/json/parser.test.ts | 6 +- circuits/test/json/parsing_types.test.ts | 6 +- circuits/test/json/stack.test.ts | 2 - circuits/test/json/values.test.ts | 2 +- circuits/test/utils/array.test.ts | 8 +- circuits/test/utils/bits.test.ts | 25 -- circuits/test/utils/hash.test.ts | 301 ++++++------------ circuits/test/utils/operators.test.ts | 3 - circuits/test/utils/search.test.ts | 39 --- circuits/utils/bits.circom | 19 -- circuits/utils/hash.circom | 67 +--- circuits/utils/search.circom | 36 --- 18 files changed, 210 insertions(+), 517 deletions(-) rename circuits/chacha20/{nivc/chacha20_nivc.circom => authentication.circom} (91%) rename circuits/test/chacha20/{chacha20-nivc.test.ts => authentication.test.ts} (92%) delete mode 100644 circuits/test/utils/bits.test.ts delete mode 100644 circuits/test/utils/search.test.ts delete mode 100644 circuits/utils/search.circom diff --git a/circuits/chacha20/nivc/chacha20_nivc.circom b/circuits/chacha20/authentication.circom similarity index 91% rename from circuits/chacha20/nivc/chacha20_nivc.circom rename to circuits/chacha20/authentication.circom index 4198ce7..405b313 100644 --- a/circuits/chacha20/nivc/chacha20_nivc.circom +++ b/circuits/chacha20/authentication.circom @@ -2,11 +2,11 @@ // modified for our needs pragma circom 2.1.9; -include "../chacha-round.circom"; -include "../chacha-qr.circom"; -include "../../utils/bits.circom"; -include "../../utils/hash.circom"; -include "../../utils/array.circom"; +include "chacha-round.circom"; +include "chacha-qr.circom"; +include "../utils/bits.circom"; +include "../utils/hash.circom"; +include "../utils/array.circom"; include "circomlib/circuits/poseidon.circom"; @@ -24,7 +24,7 @@ include "circomlib/circuits/poseidon.circom"; // | # | N | N | N | // +---+---+---+---+ // paramaterized by `DATA_BYTES` which is the plaintext length in bytes -template ChaCha20_NIVC(DATA_BYTES) { +template PlaintextAuthentication(DATA_BYTES) { // key => 8 32-bit words = 32 bytes signal input key[8][32]; // nonce => 3 32-bit words = 12 bytes @@ -34,7 +34,7 @@ template ChaCha20_NIVC(DATA_BYTES) { // the below can be both ciphertext or plaintext depending on the direction // in => N 32-bit words => N 4 byte words - signal input plainText[DATA_BYTES]; + signal input plaintext[DATA_BYTES]; // step_in should be the ciphertext digest + the HTTP digests + JSON seq digest signal input step_in[1]; @@ -48,8 +48,8 @@ template ChaCha20_NIVC(DATA_BYTES) { for (var i = 0 ; i < DATA_BYTES / 4 ; i++) { toBits[i] = fromWords32ToLittleEndian(); for (var j = 0 ; j < 4 ; j++) { - isPadding[i * 4 + j] <== IsEqual()([plainText[i * 4 + j], -1]); - toBits[i].words[j] <== (1 - isPadding[i * 4 + j]) * plainText[i*4 + j]; + isPadding[i * 4 + j] <== IsEqual()([plaintext[i * 4 + j], -1]); + toBits[i].words[j] <== (1 - isPadding[i * 4 + j]) * plaintext[i*4 + j]; } plaintextBits[i] <== toBits[i].data; } @@ -147,7 +147,7 @@ template ChaCha20_NIVC(DATA_BYTES) { signal zeroed_plaintext[DATA_BYTES]; for(var i = 0 ; i < DATA_BYTES ; i++) { // Sets any padding bytes to zero (which are presumably at the end) so they don't accum into the poly hash - zeroed_plaintext[i] <== (1 - isPadding[i]) * plainText[i]; + zeroed_plaintext[i] <== (1 - isPadding[i]) * plaintext[i]; } signal plaintext_digest <== PolynomialDigest(DATA_BYTES)(zeroed_plaintext, ciphertext_digest); signal plaintext_digest_hashed <== Poseidon(1)([plaintext_digest]); diff --git a/circuits/test/chacha20/chacha20-nivc.test.ts b/circuits/test/chacha20/authentication.test.ts similarity index 92% rename from circuits/test/chacha20/chacha20-nivc.test.ts rename to circuits/test/chacha20/authentication.test.ts index 207dc68..972abf0 100644 --- a/circuits/test/chacha20/chacha20-nivc.test.ts +++ b/circuits/test/chacha20/authentication.test.ts @@ -4,14 +4,13 @@ import { DataHasher } from "../common/poseidon"; import { assert } from "chai"; import { poseidon1 } from "poseidon-lite"; - -describe("chacha20-nivc", () => { - let circuit: WitnessTester<["key", "nonce", "counter", "plainText", "step_in"], ["step_out"]>; +describe("Plaintext Authentication", () => { + let circuit: WitnessTester<["key", "nonce", "counter", "plaintext", "step_in"], ["step_out"]>; describe("16 block test", () => { it("should perform encryption", async () => { - circuit = await circomkit.WitnessTester(`ChaCha20`, { - file: "chacha20/nivc/chacha20_nivc", - template: "ChaCha20_NIVC", + circuit = await circomkit.WitnessTester(`PlaintextAuthentication`, { + file: "chacha20/authentication", + template: "PlaintextAuthentication", params: [64] // number of bytes for plaintext }); // Test case from RCF https://www.rfc-editor.org/rfc/rfc7539.html#section-2.4.2 @@ -55,7 +54,7 @@ describe("chacha20-nivc", () => { key: toInput(Buffer.from(keyBytes)), nonce: toInput(Buffer.from(nonceBytes)), counter: counterBits, - plainText: plaintextBytes, + plaintext: plaintextBytes, step_in: 0 }, (["step_out"])); // Output @@ -68,9 +67,9 @@ describe("chacha20-nivc", () => { describe("padded plaintext", () => { it("should perform encryption", async () => { - circuit = await circomkit.WitnessTester(`ChaCha20`, { - file: "chacha20/nivc/chacha20_nivc", - template: "ChaCha20_NIVC", + circuit = await circomkit.WitnessTester(`PlaintextAuthentication`, { + file: "chacha20/authentication", + template: "PlaintextAuthentication", params: [128] // number of bytes in plaintext }); // Test case from RCF https://www.rfc-editor.org/rfc/rfc7539.html#section-2.4.2 @@ -113,7 +112,7 @@ describe("chacha20-nivc", () => { key: toInput(Buffer.from(keyBytes)), nonce: toInput(Buffer.from(nonceBytes)), counter: counterBits, - plainText: paddedPlaintextBytes, + plaintext: paddedPlaintextBytes, step_in: 0 }, (["step_out"])); let ciphertext_digest = DataHasher(ciphertextBytes); diff --git a/circuits/test/chacha20/chacha20.test.ts b/circuits/test/chacha20/chacha20.test.ts index bfe5a38..b16a739 100644 --- a/circuits/test/chacha20/chacha20.test.ts +++ b/circuits/test/chacha20/chacha20.test.ts @@ -1,7 +1,7 @@ import { WitnessTester } from "circomkit"; import { circomkit, hexToBits, toUint32Array, uintArray32ToBits } from "../common"; -describe("chacha20", () => { +describe("ChaCha20", () => { describe("qtr-round", () => { let circuit: WitnessTester<["in"], ["out"]>; it("should perform qtr-round", async () => { @@ -10,16 +10,16 @@ describe("chacha20", () => { template: "QR", }); // Test case from RCF https://www.rfc-editor.org/rfc/rfc7539.html#section-2.1 - let input = [ + let input = [ hexToBits("0x11111111"), hexToBits("0x01020304"), hexToBits("0x9b8d6f43"), hexToBits("0x01234567") ]; - let expected = [ - hexToBits("0xea2a92f4"), - hexToBits("0xcb1cf8ce"), - hexToBits("0x4581472e"), + let expected = [ + hexToBits("0xea2a92f4"), + hexToBits("0xcb1cf8ce"), + hexToBits("0x4581472e"), hexToBits("0x5881c4bb") ]; await circuit.expectPass({ in: input }, { out: expected }); @@ -34,17 +34,17 @@ describe("chacha20", () => { template: "Round", }); // Test case from RCF https://www.rfc-editor.org/rfc/rfc7539.html#section-2.1 - let input = [ - hexToBits("61707865"), hexToBits("3320646e"), hexToBits("79622d32"), hexToBits("6b206574"), - hexToBits("03020100"), hexToBits("07060504"), hexToBits("0b0a0908"), hexToBits("0f0e0d0c"), - hexToBits("13121110"), hexToBits("17161514"), hexToBits("1b1a1918"), hexToBits("1f1e1d1c"), - hexToBits("00000001"), hexToBits("09000000"), hexToBits("4a000000"), hexToBits("00000000") + let input = [ + hexToBits("61707865"), hexToBits("3320646e"), hexToBits("79622d32"), hexToBits("6b206574"), + hexToBits("03020100"), hexToBits("07060504"), hexToBits("0b0a0908"), hexToBits("0f0e0d0c"), + hexToBits("13121110"), hexToBits("17161514"), hexToBits("1b1a1918"), hexToBits("1f1e1d1c"), + hexToBits("00000001"), hexToBits("09000000"), hexToBits("4a000000"), hexToBits("00000000") ]; - let expected = [ - hexToBits("e4e7f110"), hexToBits("15593bd1"), hexToBits("1fdd0f50"), hexToBits("c47120a3"), - hexToBits("c7f4d1c7"), hexToBits("0368c033"), hexToBits("9aaa2204"), hexToBits("4e6cd4c3"), - hexToBits("466482d2"), hexToBits("09aa9f07"), hexToBits("05d7c214"), hexToBits("a2028bd9"), - hexToBits("d19c12b5"), hexToBits("b94e16de"), hexToBits("e883d0cb"), hexToBits("4e3c50a2") + let expected = [ + hexToBits("e4e7f110"), hexToBits("15593bd1"), hexToBits("1fdd0f50"), hexToBits("c47120a3"), + hexToBits("c7f4d1c7"), hexToBits("0368c033"), hexToBits("9aaa2204"), hexToBits("4e6cd4c3"), + hexToBits("466482d2"), hexToBits("09aa9f07"), hexToBits("05d7c214"), hexToBits("a2028bd9"), + hexToBits("d19c12b5"), hexToBits("b94e16de"), hexToBits("e883d0cb"), hexToBits("4e3c50a2") ]; await circuit.expectPass({ in: input }, { out: expected }); }); @@ -65,59 +65,60 @@ describe("chacha20", () => { // to ensure that every 32 bit word is byte reversed before being turned into bits. // i think this should be easy when we compute witness in rust. let test = { - keyBytes: Buffer.from( - [ - 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f - ] - ), - nonceBytes: Buffer.from( - [ - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, - 0x00, 0x00, 0x00, 0x00 - ] - ), - counter: 1, - plaintextBytes: Buffer.from( - [ - 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, - 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, - ] - ), - ciphertextBytes: Buffer.from( - [ - 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, - 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, - 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, - 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8 - ] - )} + keyBytes: Buffer.from( + [ + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f + ] + ), + nonceBytes: Buffer.from( + [ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00 + ] + ), + counter: 1, + plaintextBytes: Buffer.from( + [ + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + ] + ), + ciphertextBytes: Buffer.from( + [ + 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, + 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, + 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, + 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8 + ] + ) + } const ciphertextBits = uintArray32ToBits(toUint32Array(test.ciphertextBytes)) const plaintextBits = uintArray32ToBits(toUint32Array(test.plaintextBytes)) - const counterBits = uintArray32ToBits([test.counter])[0] - await circuit.expectPass({ - key: uintArray32ToBits(toUint32Array(test.keyBytes)), - nonce: uintArray32ToBits(toUint32Array(test.nonceBytes)), - counter: counterBits, - in: plaintextBits, - }, { out: ciphertextBits }); + const counterBits = uintArray32ToBits([test.counter])[0] + await circuit.expectPass({ + key: uintArray32ToBits(toUint32Array(test.keyBytes)), + nonce: uintArray32ToBits(toUint32Array(test.nonceBytes)), + counter: counterBits, + in: plaintextBits, + }, { out: ciphertextBits }); /// decryption since symmetric - const w2 = await circuit.expectPass({ - key: uintArray32ToBits(toUint32Array(test.keyBytes)), - nonce: uintArray32ToBits(toUint32Array(test.nonceBytes)), - counter: counterBits, - in: ciphertextBits, - }, { out: plaintextBits }); + const w2 = await circuit.expectPass({ + key: uintArray32ToBits(toUint32Array(test.keyBytes)), + nonce: uintArray32ToBits(toUint32Array(test.nonceBytes)), + counter: counterBits, + in: ciphertextBits, + }, { out: plaintextBits }); }); }); }); \ No newline at end of file diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 1ecb107..4917608 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -1,7 +1,6 @@ import { assert } from "chai"; -import { circomkit, WitnessTester, toByte, uintArray32ToBits, http_response_plaintext, http_response_ciphertext, http_start_line, http_header_0, http_header_1, http_body, PolynomialDigest, strToBytes, JsonMaskType, jsonTreeHasher, compressTreeHash, modAdd, InitialDigest, MockManifest } from "../common"; -import { DataHasher } from "../common/poseidon"; -import { toInput } from "../chacha20/chacha20-nivc.test"; +import { circomkit, WitnessTester, uintArray32ToBits, http_response_plaintext, http_response_ciphertext, http_start_line, http_header_0, http_header_1, http_body, PolynomialDigest, strToBytes, JsonMaskType, jsonTreeHasher, compressTreeHash, modAdd, InitialDigest, MockManifest } from "../common"; +import { toInput } from "../chacha20/authentication.test"; import { poseidon1 } from "poseidon-lite"; // HTTP/1.1 200 OK @@ -28,43 +27,37 @@ const DATA_BYTES = 320; const MAX_NUMBER_OF_HEADERS = 2; const MAX_STACK_HEIGHT = 5; -// These `check_*` are currently from Rust +// These `check_*` are currently from Rust to ensure we have parity const check_ciphertext_digest = BigInt("5947802862726868637928743536818722886587721698845887498686185738472802646104"); -const check_init_nivc_input = BigInt("1004047589511714647691705222985203827421588749970619269541141824992822853087"); +const check_init_nivc_input = BigInt("10288873638660630335427615297930270928433661836597941144520949467184902553219"); const [ciphertext_digest, init_nivc_input] = InitialDigest(MockManifest(), http_response_ciphertext, MAX_STACK_HEIGHT); -// TODO: Fix these -// assert.deepEqual(ciphertext_digest, check_ciphertext_digest); -// assert.deepEqual(init_nivc_input, check_init_nivc_input); - -const value = strToBytes("Taylor Swift"); +assert.deepEqual(ciphertext_digest, check_ciphertext_digest); +assert.deepEqual(init_nivc_input, check_init_nivc_input); describe("Example NIVC Proof", async () => { - let PlaintextAuthentication: WitnessTester<["step_in", "plainText", "key", "nonce", "counter"], ["step_out"]>; + let PlaintextAuthentication: WitnessTester<["step_in", "plaintext", "key", "nonce", "counter"], ["step_out"]>; let HTTPVerification: WitnessTester<["step_in", "ciphertext_digest", "data", "main_digests"], ["step_out"]>; let JSONExtraction: WitnessTester<["step_in", "ciphertext_digest", "data", "sequence_digest", "value_digest"], ["step_out"]>; before(async () => { PlaintextAuthentication = await circomkit.WitnessTester("PlaintextAuthentication", { - file: "chacha20/nivc/chacha20_nivc", - template: "ChaCha20_NIVC", + file: "chacha20/authentication", + template: "PlaintextAuthentication", params: [DATA_BYTES] }); - console.log("#constraints (PlaintextAuthentication):", await PlaintextAuthentication.getConstraintCount()); HTTPVerification = await circomkit.WitnessTester("HTTPVerification", { file: "http/verification", template: "HTTPVerification", params: [DATA_BYTES, MAX_NUMBER_OF_HEADERS], }); - console.log("#constraints (HTTPVerification):", await HTTPVerification.getConstraintCount()); JSONExtraction = await circomkit.WitnessTester(`JSONExtraction`, { file: "json/extraction", template: "JSONExtraction", params: [DATA_BYTES, MAX_STACK_HEIGHT], }); - console.log("#constraints (JSONExtraction):", await JSONExtraction.getConstraintCount()); }); it("Spotify Example", async () => { @@ -74,12 +67,11 @@ describe("Example NIVC Proof", async () => { const nonceIn = toInput(Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00])); let plaintext_authentication = await PlaintextAuthentication.compute({ step_in: init_nivc_input, - plainText: http_response_plaintext, + plaintext: http_response_plaintext, key: keyIn, nonce: nonceIn, counter: counterBits, }, ["step_out"]); - console.log("Plaintext Authentication `step_out`:", plaintext_authentication.step_out); const http_response_plaintext_digest = PolynomialDigest(http_response_plaintext, ciphertext_digest); const http_response_plaintext_digest_hashed = poseidon1([http_response_plaintext_digest]); const correct_plaintext_authentication_step_out = modAdd(init_nivc_input - ciphertext_digest, http_response_plaintext_digest_hashed); @@ -91,7 +83,6 @@ describe("Example NIVC Proof", async () => { const header_1_digest = PolynomialDigest(http_header_1, ciphertext_digest); const padded_http_body = http_body.concat(Array(320 - http_body.length).fill(-1)); let step_in = BigInt(plaintext_authentication.step_out.toString(10)); - console.log("http_step_in: ", step_in); let http_verification = await HTTPVerification.compute({ step_in, ciphertext_digest, @@ -100,7 +91,6 @@ describe("Example NIVC Proof", async () => { }, ["step_out"]); // (autoparallel) This next line gives me an aneurysm let http_verification_step_out = BigInt((http_verification.step_out as number[])[0]); - console.log("HTTP Verification `step_out`:", http_verification_step_out); const body_digest_hashed = poseidon1([PolynomialDigest(http_body, ciphertext_digest)]); const start_line_digest_digest_hashed = poseidon1([start_line_digest]); const header_0_digest_hashed = poseidon1([header_0_digest]); @@ -126,9 +116,6 @@ describe("Example NIVC Proof", async () => { const sequence_digest = compressTreeHash(ciphertext_digest, [stack, treeHashes]); const value_digest = PolynomialDigest(targetValue, ciphertext_digest); - const sequence_digest_hashed = poseidon1([sequence_digest]); - console.log("sequence_digest_hashed = ", sequence_digest_hashed); - let json_extraction = await JSONExtraction.compute({ step_in: http_verification_step_out, ciphertext_digest, @@ -136,7 +123,6 @@ describe("Example NIVC Proof", async () => { value_digest, sequence_digest, }, ["step_out"]); - console.log("JSON Extraction `step_out`:", json_extraction.step_out); assert.deepEqual(json_extraction.step_out, value_digest); }); }); diff --git a/circuits/test/http/verification.test.ts b/circuits/test/http/verification.test.ts index 3a9011b..ce97d66 100644 --- a/circuits/test/http/verification.test.ts +++ b/circuits/test/http/verification.test.ts @@ -1,7 +1,6 @@ import { circomkit, WitnessTester, PolynomialDigest, http_response_plaintext, http_start_line, http_header_0, http_header_1, http_body, modAdd } from "../common"; import { assert } from "chai"; -import { DataHasher } from "../common/poseidon"; -import { poseidon1, poseidon2 } from "poseidon-lite"; +import { poseidon1 } from "poseidon-lite"; // HTTP/1.1 200 OK // content-type: application/json; charset=utf-8 diff --git a/circuits/test/json/extraction.test.ts b/circuits/test/json/extraction.test.ts index b910888..152df1a 100644 --- a/circuits/test/json/extraction.test.ts +++ b/circuits/test/json/extraction.test.ts @@ -15,7 +15,6 @@ describe("JSON Extraction", () => { template: "JSONExtraction", params: [input.length, MAX_STACK_HEIGHT], }); - console.log("#constraints:", await hash_parser.getConstraintCount()); // Test `42` in 0th slot let targetValue = strToBytes("42"); @@ -71,7 +70,6 @@ describe("JSON Extraction", () => { template: "JSONExtraction", params: [input.length, MAX_STACK_HEIGHT], }); - console.log("#constraints:", await hash_parser.getConstraintCount()); // Test `420` in "k"'s 0th slot let targetValue = strToBytes("420"); @@ -125,7 +123,6 @@ describe("JSON Extraction", () => { template: "JSONExtraction", params: [input.length, 5], }); - console.log("#constraints:", await hash_parser.getConstraintCount()); const KEY0 = strToBytes("a"); const KEY1 = strToBytes("b"); @@ -163,7 +160,6 @@ describe("JSON Extraction", () => { template: "JSONExtraction", params: [input.length, 5], }); - console.log("#constraints:", await hash_parser.getConstraintCount()); const KEY0 = strToBytes("data"); const KEY1 = strToBytes("items"); diff --git a/circuits/test/json/parser.test.ts b/circuits/test/json/parser.test.ts index 7965425..0c525b0 100644 --- a/circuits/test/json/parser.test.ts +++ b/circuits/test/json/parser.test.ts @@ -1,6 +1,6 @@ -import { circomkit, WitnessTester, generateDescription, readJSONInputFile } from "../common"; +import { circomkit, WitnessTester, readJSONInputFile } from "../common"; -describe("json-parser", () => { +describe("JSON Parser", () => { let circuit: WitnessTester<["data"]>; it(`array only input`, async () => { @@ -12,7 +12,6 @@ describe("json-parser", () => { template: "Parser", params: [input.length, 2], }); - console.log("#constraints:", await circuit.getConstraintCount()); await circuit.expectPass({ data: input @@ -28,7 +27,6 @@ describe("json-parser", () => { template: "Parser", params: [input.length, 3], }); - console.log("#constraints:", await circuit.getConstraintCount()); await circuit.expectPass({ data: input diff --git a/circuits/test/json/parsing_types.test.ts b/circuits/test/json/parsing_types.test.ts index 8e4a3eb..a803fc3 100644 --- a/circuits/test/json/parsing_types.test.ts +++ b/circuits/test/json/parsing_types.test.ts @@ -1,7 +1,5 @@ import { circomkit, WitnessTester, generateDescription } from "../common"; -import { Delimiters, WhiteSpace, Numbers, Escape, INITIAL_IN, INITIAL_OUT } from '.'; - - +import { Delimiters, WhiteSpace, INITIAL_IN, INITIAL_OUT } from '.'; describe("StateUpdate", () => { let circuit: WitnessTester< @@ -23,8 +21,6 @@ describe("StateUpdate", () => { template: "StateUpdate", params: [4], }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); //-TEST_1----------------------------------------------------------// diff --git a/circuits/test/json/stack.test.ts b/circuits/test/json/stack.test.ts index fc3d5b6..6140d64 100644 --- a/circuits/test/json/stack.test.ts +++ b/circuits/test/json/stack.test.ts @@ -9,7 +9,6 @@ describe("GetTopOfStack", () => { template: "GetTopOfStack", params: [4], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); function generatePassCase(input: any, expected: any) { @@ -38,7 +37,6 @@ describe("StateUpdate :: RewriteStack", () => { template: "StateUpdate", params: [4], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); function generatePassCase(input: any, expected: any, desc: string) { diff --git a/circuits/test/json/values.test.ts b/circuits/test/json/values.test.ts index 31fadcd..f51f43b 100644 --- a/circuits/test/json/values.test.ts +++ b/circuits/test/json/values.test.ts @@ -12,8 +12,8 @@ describe("StateUpdate :: Values", () => { template: "StateUpdate", params: [4], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); + function generatePassCase(input: any, expected: any, desc: string) { const description = generateDescription(input); diff --git a/circuits/test/utils/array.test.ts b/circuits/test/utils/array.test.ts index 1202a47..2b88325 100644 --- a/circuits/test/utils/array.test.ts +++ b/circuits/test/utils/array.test.ts @@ -1,4 +1,5 @@ import { circomkit, WitnessTester } from "../common"; + describe("IsEqualArray", () => { let circuit: WitnessTester<["in"], ["out"]>; before(async () => { @@ -7,7 +8,6 @@ describe("IsEqualArray", () => { template: "IsEqualArray", params: [3], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: [[0,0,0],[0,0,0]]", async () => { @@ -61,7 +61,6 @@ describe("Contains", () => { template: "Contains", params: [3], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: in = 0, array = [0,1,2]", async () => { @@ -102,7 +101,6 @@ describe("ArrayAdd", () => { template: "ArrayAdd", params: [3], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: lhs = [0,1,2], rhs = [3,5,7]", async () => { @@ -122,7 +120,6 @@ describe("ArrayMul", () => { template: "ArrayMul", params: [3], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: lhs = [0,1,2], rhs = [3,5,7]", async () => { @@ -142,7 +139,6 @@ describe("GenericArrayAdd", () => { template: "GenericArrayAdd", params: [3, 2], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: arrays = [[0,1,2],[3,5,7]]", async () => { @@ -161,7 +157,6 @@ describe("fromLittleEndianToWords32", () => { file: "utils/array", template: "fromLittleEndianToWords32", }); - console.log("#constraints:", await circuit.getConstraintCount()); let input = [ 0, 1, 0, 1, 0, 0, 0, 0, 0, @@ -180,7 +175,6 @@ describe("fromWords32ToLittleEndian", () => { file: "utils/array", template: "fromWords32ToLittleEndian", }); - console.log("#constraints:", await circuit.getConstraintCount()); let input = [72, 84, 84, 80]; await circuit.expectPass({ words: input }, { diff --git a/circuits/test/utils/bits.test.ts b/circuits/test/utils/bits.test.ts deleted file mode 100644 index 30dfdc4..0000000 --- a/circuits/test/utils/bits.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { circomkit, WitnessTester } from "../common"; - -describe("ASCII", () => { - let circuit: WitnessTester<["in"], ["out"]>; - before(async () => { - circuit = await circomkit.WitnessTester(`ASCII`, { - file: "utils/bits", - template: "ASCII", - params: [13], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); - - it("(valid) witness: in = b\"Hello, world!\"", async () => { - await circuit.expectPass( - { in: [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33] }, - ); - }); - - it("(invalid) witness: in = [256, ...]", async () => { - await circuit.expectFail( - { in: [256, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33] } - ); - }); -}); \ No newline at end of file diff --git a/circuits/test/utils/hash.test.ts b/circuits/test/utils/hash.test.ts index 94733b9..3c8718a 100644 --- a/circuits/test/utils/hash.test.ts +++ b/circuits/test/utils/hash.test.ts @@ -1,230 +1,141 @@ import assert from "assert"; -import { circomkit, PolynomialDigest, WitnessTester } from "../common"; +import { circomkit, http_response_plaintext, http_start_line, PolynomialDigest, WitnessTester } from "../common"; import { DataHasher, PoseidonModular } from "../common/poseidon"; import { poseidon1 } from "poseidon-lite"; -describe("hash", () => { - describe("PoseidonModular_16", () => { - let circuit: WitnessTester<["in"], ["out"]>; - - before(async () => { - circuit = await circomkit.WitnessTester(`PoseidonModular`, { - file: "utils/hash", - template: "PoseidonModular", - params: [16], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); - it("witness: in = [16*random]", async () => { - const input = Array.from({ length: 16 }, () => Math.floor(Math.random() * 256)); - const hash = PoseidonModular(input); +describe("DataHasher", () => { + let circuit: WitnessTester<["in"], ["out"]>; - await circuit.expectPass( - { in: input }, - { out: hash } - ); + before(async () => { + circuit = await circomkit.WitnessTester(`DataHasher`, { + file: "utils/hash", + template: "DataHasher", + params: [16], }); }); - describe("PoseidonModular_379", () => { - let circuit: WitnessTester<["in"], ["out"]>; - - before(async () => { - circuit = await circomkit.WitnessTester(`PoseidonModular`, { - file: "utils/hash", - template: "PoseidonModular", - params: [379], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); - - it("witness: in = [379*random]", async () => { - const input = Array.from({ length: 379 }, () => Math.floor(Math.random() * 256)); - const hash = PoseidonModular(input); - - await circuit.expectPass( - { in: input }, - { out: hash } - ); - }); + let all_zero_hash = BigInt("14744269619966411208579211824598458697587494354926760081771325075741142829156"); + it("witness: in = [0,...x16]", async () => { + const input = Array(16).fill(0); + await circuit.expectPass( + { in: input }, + { out: all_zero_hash } + ); + }); + // Check that TS version of DataHasher also is correct + assert.deepEqual(DataHasher(Array(16).fill(0)), all_zero_hash); + + it("witness: in = [-1,...x16]", async () => { + const input = Array(16).fill(-1); + await circuit.expectPass( + { in: input }, + { out: 0 } + ); + }); + // Check that TS version of DataHasher also is correct + assert.deepEqual(DataHasher(Array(16).fill(-1)), 0); + + it("witness: in = [1,0,...x15]", async () => { + let input = Array(16).fill(0); + input[0] = 1; + const hash = PoseidonModular([0, 1]); + await circuit.expectPass( + { in: input }, + { out: hash } + ); }); - describe("PoseidonChainer", () => { - let circuit: WitnessTester<["in"], ["out"]>; - before(async () => { - circuit = await circomkit.WitnessTester(`PoseidonChainer`, { - file: "utils/hash", - template: "PoseidonChainer", - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); - - it("witness: in = [69,420]", async () => { - const input = [69, 420]; - const hash = PoseidonModular(input); - await circuit.expectPass( - { in: input }, - { out: hash } - ); - }); + it("witness: in = [0,0,...x15,1]", async () => { + let input = Array(16).fill(0); + input[15] = 1; + const hash = PoseidonModular([0, "1329227995784915872903807060280344576"]); + await circuit.expectPass( + { in: input }, + { out: hash } + ); }); +}); - describe("DataHasher", () => { - let circuit: WitnessTester<["in"], ["out"]>; +const padded_http_start_line = http_start_line.concat(Array(320 - http_start_line.length).fill(-1)); - before(async () => { - circuit = await circomkit.WitnessTester(`DataHasher`, { - file: "utils/hash", - template: "DataHasher", - params: [16], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); +describe("DataHasherHTTP", () => { + let circuit: WitnessTester<["in"], ["out"]>; + let circuit_small: WitnessTester<["in"], ["out"]>; - let all_zero_hash = BigInt("14744269619966411208579211824598458697587494354926760081771325075741142829156"); - it("witness: in = [0,...x16]", async () => { - const input = Array(16).fill(0); - await circuit.expectPass( - { in: input }, - { out: all_zero_hash } - ); - }); - // Check that TS version of DataHasher also is correct - assert.deepEqual(DataHasher(Array(16).fill(0)), all_zero_hash); - - it("witness: in = [-1,...x16]", async () => { - const input = Array(16).fill(-1); - await circuit.expectPass( - { in: input }, - { out: 0 } - ); - }); - // Check that TS version of DataHasher also is correct - assert.deepEqual(DataHasher(Array(16).fill(-1)), 0); - - it("witness: in = [1,0,...x15]", async () => { - let input = Array(16).fill(0); - input[0] = 1; - const hash = PoseidonModular([0, 1]); - await circuit.expectPass( - { in: input }, - { out: hash } - ); + before(async () => { + circuit = await circomkit.WitnessTester(`DataHasher`, { + file: "utils/hash", + template: "DataHasher", + params: [320], }); - - it("witness: in = [0,0,...x15,1]", async () => { - let input = Array(16).fill(0); - input[15] = 1; - const hash = PoseidonModular([0, "1329227995784915872903807060280344576"]); - await circuit.expectPass( - { in: input }, - { out: hash } - ); + circuit_small = await circomkit.WitnessTester(`DataHasher`, { + file: "utils/hash", + template: "DataHasher", + params: [32], }); }); - const TEST_HTTP_BYTES = [ - 72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10, 99, 111, 110, 116, 101, 110, - 116, 45, 116, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, - 115, 111, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 116, 102, 45, 56, 13, 10, 99, - 111, 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 58, 32, 103, 122, 105, - 112, 13, 10, 84, 114, 97, 110, 115, 102, 101, 114, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, - 32, 99, 104, 117, 110, 107, 101, 100, 13, 10, 13, 10, 123, 13, 10, 32, 32, 32, 34, 100, 97, 116, - 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, - 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, - 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, - 111, 102, 105, 108, 101, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 84, 97, 121, 108, 111, 114, 32, 83, 119, - 105, 102, 116, 34, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, - 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, - 10, 32, 32, 32, 125, 13, 10, 125] - - const http_start_line = [72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10]; - const padded_http_start_line = http_start_line.concat(Array(320 - http_start_line.length).fill(-1)); - - describe("DataHasherHTTP", () => { - let circuit: WitnessTester<["in"], ["out"]>; - let circuit_small: WitnessTester<["in"], ["out"]>; - - before(async () => { - circuit = await circomkit.WitnessTester(`DataHasher`, { - file: "utils/hash", - template: "DataHasher", - params: [320], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - - circuit_small = await circomkit.WitnessTester(`DataHasher`, { - file: "utils/hash", - template: "DataHasher", - params: [32], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); - - it("witness: HTTP bytes", async () => { - let hash = DataHasher(TEST_HTTP_BYTES); - assert.deepEqual(String(hash), "2195365663909569734943279727560535141179588918483111718403427949138562480675"); - await circuit.expectPass({ in: TEST_HTTP_BYTES }, { out: "2195365663909569734943279727560535141179588918483111718403427949138562480675" }); - }); + it("witness: HTTP bytes", async () => { + let hash = DataHasher(http_response_plaintext); + assert.deepEqual(String(hash), "2195365663909569734943279727560535141179588918483111718403427949138562480675"); + await circuit.expectPass({ in: http_response_plaintext }, { out: "2195365663909569734943279727560535141179588918483111718403427949138562480675" }); + }); - let padded_hash = DataHasher(padded_http_start_line); - it("witness: padded HTTP start line", async () => { - await circuit.expectPass({ in: padded_http_start_line }, { out: padded_hash }); - }); + let padded_hash = DataHasher(padded_http_start_line); + it("witness: padded HTTP start line", async () => { + await circuit.expectPass({ in: padded_http_start_line }, { out: padded_hash }); + }); - let hash = DataHasher(http_start_line); - it("witness: unpadded HTTP start line", async () => { - await circuit_small.expectPass({ in: http_start_line.concat(Array(32 - http_start_line.length).fill(-1)) }, { out: hash }); - }); + let hash = DataHasher(http_start_line); + it("witness: unpadded HTTP start line", async () => { + await circuit_small.expectPass({ in: http_start_line.concat(Array(32 - http_start_line.length).fill(-1)) }, { out: hash }); }); +}); - describe("PolynomialDigest", () => { - let circuit: WitnessTester<["bytes", "polynomial_input"], ["digest"]>; +describe("PolynomialDigest", () => { + let circuit: WitnessTester<["bytes", "polynomial_input"], ["digest"]>; - before(async () => { - circuit = await circomkit.WitnessTester(`PolynomialDigest`, { - file: "utils/hash", - template: "PolynomialDigest", - params: [4], - }); - console.log("#constraints:", await circuit.getConstraintCount()); + before(async () => { + circuit = await circomkit.WitnessTester(`PolynomialDigest`, { + file: "utils/hash", + template: "PolynomialDigest", + params: [4], }); + }); - it("witness: bytes = [0,0,0,0], polynomial_input = 1", async () => { - const bytes = [0, 0, 0, 0]; - const polynomial_input = 0; - - await circuit.expectPass( - { bytes, polynomial_input }, - { digest: 0 } - ); - }); + it("witness: bytes = [0,0,0,0], polynomial_input = 1", async () => { + const bytes = [0, 0, 0, 0]; + const polynomial_input = 0; - it("witness: bytes = [1,2,3,4], polynomial_input = 7", async () => { - const bytes = [1, 2, 3, 4]; - const polynomial_input = 7; + await circuit.expectPass( + { bytes, polynomial_input }, + { digest: 0 } + ); + }); - await circuit.expectPass( - { bytes, polynomial_input }, - { digest: 1 + 2 * 7 + 3 * 7 ** 2 + 4 * 7 ** 3 } - ); - }); + it("witness: bytes = [1,2,3,4], polynomial_input = 7", async () => { + const bytes = [1, 2, 3, 4]; + const polynomial_input = 7; - it("witness: bytes = [4*random], polynomial_input = random", async () => { - const bytes = Array.from({ length: 4 }, () => Math.floor(Math.random() * 256)); - const polynomial_input = poseidon1([BigInt(Math.floor(Math.random() * 694206942069420))]); - const digest = PolynomialDigest(bytes, polynomial_input); + await circuit.expectPass( + { bytes, polynomial_input }, + { digest: 1 + 2 * 7 + 3 * 7 ** 2 + 4 * 7 ** 3 } + ); + }); - await circuit.expectPass( - { bytes, polynomial_input }, - { digest } - ); - }); + it("witness: bytes = [4*random], polynomial_input = random", async () => { + const bytes = Array.from({ length: 4 }, () => Math.floor(Math.random() * 256)); + const polynomial_input = poseidon1([BigInt(Math.floor(Math.random() * 694206942069420))]); + const digest = PolynomialDigest(bytes, polynomial_input); + await circuit.expectPass( + { bytes, polynomial_input }, + { digest } + ); }); + }); + diff --git a/circuits/test/utils/operators.test.ts b/circuits/test/utils/operators.test.ts index 67c0069..1635a10 100644 --- a/circuits/test/utils/operators.test.ts +++ b/circuits/test/utils/operators.test.ts @@ -8,7 +8,6 @@ describe("SwitchArray", () => { template: "SwitchArray", params: [3, 2], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: case = 0, branches = [0, 1, 2], vals = [[69,0], [420,1], [1337,2]]", async () => { @@ -63,7 +62,6 @@ describe("Switch", () => { template: "Switch", params: [3], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: case = 0, branches = [0, 1, 2], vals = [69, 420, 1337]", async () => { @@ -105,7 +103,6 @@ describe("InRange", () => { template: "InRange", params: [8], }); - console.log("#constraints:", await circuit.getConstraintCount()); }); it("witness: in = 1, range = [0,2]", async () => { diff --git a/circuits/test/utils/search.test.ts b/circuits/test/utils/search.test.ts deleted file mode 100644 index d05b948..0000000 --- a/circuits/test/utils/search.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { circomkit, toByte, WitnessTester } from "../common"; - -const data = toByte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum"); -const key = toByte("Ipsum"); - -describe("SubstringMatchWithIndex", () => { - let circuit: WitnessTester<["data", "key", "start"], ["out"]>; - - before(async () => { - circuit = await circomkit.WitnessTester(`SubstringSearch`, { - file: "utils/search", - template: "SubstringMatchWithIndex", - params: [data.length, key.length], - }); - console.log("#constraints:", await circuit.getConstraintCount()); - }); - - it("data = witness.json:data, key = witness.json:key, r = hash(key+data)", async () => { - await circuit.expectPass( - { - data: data, - key: key, - start: 6 - }, - { out: 1 }, - ); - }); - - it("data = witness.json:data, key = witness.json:key, r = hash(key+data), output false", async () => { - await circuit.expectPass( - { - data: data, - key: key, - start: 98 - }, - { out: 0 } - ); - }); -}); diff --git a/circuits/utils/bits.circom b/circuits/utils/bits.circom index 08f2daf..f847aea 100644 --- a/circuits/utils/bits.circom +++ b/circuits/utils/bits.circom @@ -2,25 +2,6 @@ pragma circom 2.1.9; include "circomlib/circuits/bitify.circom"; -/* -This template passes if a given array contains only valid ASCII values (e.g., u8 vals). - -# Params: - - `n`: the length of the array - -# Inputs: - - `in[n]`: array to check -*/ -template ASCII(n) { - signal input in[n]; - - component Byte[n]; - for(var i = 0; i < n; i++) { - Byte[i] = Num2Bits(8); - Byte[i].in <== in[i]; - } -} - // initially from https://github.com/reclaimprotocol/zk-symmetric-crypto // modified for our needs diff --git a/circuits/utils/hash.circom b/circuits/utils/hash.circom index fd6e4df..5da3c12 100644 --- a/circuits/utils/hash.circom +++ b/circuits/utils/hash.circom @@ -3,69 +3,6 @@ pragma circom 2.1.9; include "circomlib/circuits/poseidon.circom"; include "./array.circom"; -/// Circuit to calculate Poseidon hash of an arbitrary number of inputs. -/// Splits input into chunks of 16 elements (or less for the last chunk) and hashes them separately -/// Then combines the chunk hashes using a binary tree structure. -/// -/// NOTE: from -/// -/// # Parameters -/// - `numElements`: Number of elements in the input array -/// -/// # Inputs -/// - `in`: Array of numElements to be hashed -/// -/// # Output -/// - `out`: Poseidon hash of the input array -template PoseidonModular(numElements) { - signal input in[numElements]; - signal output out; - - var chunks = numElements \ 16; - var last_chunk_size = numElements % 16; - if (last_chunk_size != 0) { - chunks += 1; - } - - var _out; - - for (var i = 0; i < chunks; i++) { - var start = i * 16; - var end = start + 16; - var chunk_hash; - - if (end > numElements) { // last chunk - end = numElements; - var last_chunk[last_chunk_size]; - for (var i=start ; i