From 34467f0e2c74bd0818d5b623c807652c29d1e1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Fri, 6 Dec 2024 12:39:33 +0100 Subject: [PATCH] Revert original hashing. Prepare 3 versions of hashing in the 'lib'. --- circuits/nova_snark/blur_step.compile_log | 8 +- .../nova_snark/brightness_step.compile_log | 8 +- circuits/nova_snark/contrast_step.compile_log | 8 +- circuits/nova_snark/crop_step.compile_log | 8 +- .../nova_snark/grayscale_step.compile_log | 8 +- circuits/nova_snark/hash_step.compile_log | 8 +- circuits/nova_snark/resize_step.compile_log | 8 +- .../nova_snark/sharpness_step.compile_log | 8 +- circuits/sonobe/blur_step.compile_log | 8 +- circuits/sonobe/brightness_step.compile_log | 8 +- circuits/sonobe/contrast_step.compile_log | 8 +- circuits/sonobe/crop_step.compile_log | 8 +- circuits/sonobe/grayscale_step.compile_log | 8 +- circuits/sonobe/hash_step.compile_log | 8 +- circuits/sonobe/resize_step.compile_log | 8 +- circuits/sonobe/sharpness_step.compile_log | 8 +- circuits/src/utils/hashers.circom | 117 +++++++++++++----- 17 files changed, 153 insertions(+), 92 deletions(-) diff --git a/circuits/nova_snark/blur_step.compile_log b/circuits/nova_snark/blur_step.compile_log index 966961a..c2e329c 100644 --- a/circuits/nova_snark/blur_step.compile_log +++ b/circuits/nova_snark/blur_step.compile_log @@ -1,11 +1,11 @@ -template instances: 166 -non-linear constraints: 253110 +template instances: 88 +non-linear constraints: 345126 linear constraints: 0 public inputs: 4 private inputs: 512 (none belong to witness) public outputs: 4 -wires: 245433 -labels: 619532 +wires: 337449 +labels: 866504 Written successfully: ./blur_step.r1cs Written successfully: ./blur_step_js/blur_step.wasm Everything went okay diff --git a/circuits/nova_snark/brightness_step.compile_log b/circuits/nova_snark/brightness_step.compile_log index ab5cc50..2cfe7a2 100644 --- a/circuits/nova_snark/brightness_step.compile_log +++ b/circuits/nova_snark/brightness_step.compile_log @@ -1,11 +1,11 @@ -template instances: 165 -non-linear constraints: 307272 +template instances: 87 +non-linear constraints: 353280 linear constraints: 1 public inputs: 3 private inputs: 256 public outputs: 3 -wires: 291917 -labels: 606134 +wires: 337925 +labels: 729620 Written successfully: ./brightness_step.r1cs Written successfully: ./brightness_step_js/brightness_step.wasm Everything went okay diff --git a/circuits/nova_snark/contrast_step.compile_log b/circuits/nova_snark/contrast_step.compile_log index c2e7a81..b3aad0c 100644 --- a/circuits/nova_snark/contrast_step.compile_log +++ b/circuits/nova_snark/contrast_step.compile_log @@ -1,11 +1,11 @@ -template instances: 165 -non-linear constraints: 307272 +template instances: 87 +non-linear constraints: 353280 linear constraints: 1 public inputs: 3 private inputs: 256 public outputs: 3 -wires: 291917 -labels: 606134 +wires: 337925 +labels: 729620 Written successfully: ./contrast_step.r1cs Written successfully: ./contrast_step_js/contrast_step.wasm Everything went okay diff --git a/circuits/nova_snark/crop_step.compile_log b/circuits/nova_snark/crop_step.compile_log index a5831d3..631a44c 100644 --- a/circuits/nova_snark/crop_step.compile_log +++ b/circuits/nova_snark/crop_step.compile_log @@ -1,11 +1,11 @@ -template instances: 176 -non-linear constraints: 673718 +template instances: 97 +non-linear constraints: 708224 linear constraints: 1 public inputs: 3 private inputs: 128 public outputs: 3 -wires: 673079 -labels: 2596364 +wires: 707585 +labels: 2688977 Written successfully: ./crop_step.r1cs Written successfully: ./crop_step_js/crop_step.wasm Everything went okay diff --git a/circuits/nova_snark/grayscale_step.compile_log b/circuits/nova_snark/grayscale_step.compile_log index dff5552..38ff135 100644 --- a/circuits/nova_snark/grayscale_step.compile_log +++ b/circuits/nova_snark/grayscale_step.compile_log @@ -1,11 +1,11 @@ -template instances: 164 -non-linear constraints: 122952 +template instances: 86 +non-linear constraints: 168960 linear constraints: 0 public inputs: 2 private inputs: 256 public outputs: 2 -wires: 120395 -labels: 260401 +wires: 166403 +labels: 383887 Written successfully: ./grayscale_step.r1cs Written successfully: ./grayscale_step_js/grayscale_step.wasm Everything went okay diff --git a/circuits/nova_snark/hash_step.compile_log b/circuits/nova_snark/hash_step.compile_log index 9cc26b7..61eba46 100644 --- a/circuits/nova_snark/hash_step.compile_log +++ b/circuits/nova_snark/hash_step.compile_log @@ -1,11 +1,11 @@ -template instances: 154 -non-linear constraints: 7716 +template instances: 76 +non-linear constraints: 30720 linear constraints: 0 public inputs: 1 private inputs: 128 public outputs: 1 -wires: 7846 -labels: 37463 +wires: 30850 +labels: 99206 Written successfully: ./hash_step.r1cs Written successfully: ./hash_step_js/hash_step.wasm Everything went okay diff --git a/circuits/nova_snark/resize_step.compile_log b/circuits/nova_snark/resize_step.compile_log index 470edc5..3eb1621 100644 --- a/circuits/nova_snark/resize_step.compile_log +++ b/circuits/nova_snark/resize_step.compile_log @@ -1,11 +1,11 @@ -template instances: 163 -non-linear constraints: 245904 +template instances: 84 +non-linear constraints: 337920 linear constraints: 0 public inputs: 2 private inputs: 512 (none belong to witness) public outputs: 2 -wires: 238227 -labels: 596313 +wires: 330243 +labels: 843282 Written successfully: ./resize_step.r1cs Written successfully: ./resize_step_js/resize_step.wasm Everything went okay diff --git a/circuits/nova_snark/sharpness_step.compile_log b/circuits/nova_snark/sharpness_step.compile_log index db8cdf0..88c30c4 100644 --- a/circuits/nova_snark/sharpness_step.compile_log +++ b/circuits/nova_snark/sharpness_step.compile_log @@ -1,11 +1,11 @@ -template instances: 171 -non-linear constraints: 329910 +template instances: 93 +non-linear constraints: 421926 linear constraints: 0 public inputs: 4 private inputs: 512 (128 belong to witness) public outputs: 4 -wires: 314553 -labels: 803852 +wires: 406569 +labels: 1050824 Written successfully: ./sharpness_step.r1cs Written successfully: ./sharpness_step_js/sharpness_step.wasm Everything went okay diff --git a/circuits/sonobe/blur_step.compile_log b/circuits/sonobe/blur_step.compile_log index 2c34a52..4b71b0b 100644 --- a/circuits/sonobe/blur_step.compile_log +++ b/circuits/sonobe/blur_step.compile_log @@ -1,11 +1,11 @@ -template instances: 167 -non-linear constraints: 253110 +template instances: 89 +non-linear constraints: 345126 linear constraints: 0 public inputs: 4 private inputs: 512 (none belong to witness) public outputs: 4 -wires: 245433 -labels: 621068 +wires: 337449 +labels: 868040 Written successfully: ./blur_step.r1cs Written successfully: ./blur_step_js/blur_step.wasm Everything went okay diff --git a/circuits/sonobe/brightness_step.compile_log b/circuits/sonobe/brightness_step.compile_log index 6b01181..03e8086 100644 --- a/circuits/sonobe/brightness_step.compile_log +++ b/circuits/sonobe/brightness_step.compile_log @@ -1,11 +1,11 @@ -template instances: 166 -non-linear constraints: 307272 +template instances: 88 +non-linear constraints: 353280 linear constraints: 1 public inputs: 3 private inputs: 256 public outputs: 3 -wires: 291917 -labels: 606902 +wires: 337925 +labels: 730388 Written successfully: ./brightness_step.r1cs Written successfully: ./brightness_step_js/brightness_step.wasm Everything went okay diff --git a/circuits/sonobe/contrast_step.compile_log b/circuits/sonobe/contrast_step.compile_log index 9aea78e..e0cb4a6 100644 --- a/circuits/sonobe/contrast_step.compile_log +++ b/circuits/sonobe/contrast_step.compile_log @@ -1,11 +1,11 @@ -template instances: 166 -non-linear constraints: 307272 +template instances: 88 +non-linear constraints: 353280 linear constraints: 1 public inputs: 3 private inputs: 256 public outputs: 3 -wires: 291917 -labels: 606902 +wires: 337925 +labels: 730388 Written successfully: ./contrast_step.r1cs Written successfully: ./contrast_step_js/contrast_step.wasm Everything went okay diff --git a/circuits/sonobe/crop_step.compile_log b/circuits/sonobe/crop_step.compile_log index a5831d3..631a44c 100644 --- a/circuits/sonobe/crop_step.compile_log +++ b/circuits/sonobe/crop_step.compile_log @@ -1,11 +1,11 @@ -template instances: 176 -non-linear constraints: 673718 +template instances: 97 +non-linear constraints: 708224 linear constraints: 1 public inputs: 3 private inputs: 128 public outputs: 3 -wires: 673079 -labels: 2596364 +wires: 707585 +labels: 2688977 Written successfully: ./crop_step.r1cs Written successfully: ./crop_step_js/crop_step.wasm Everything went okay diff --git a/circuits/sonobe/grayscale_step.compile_log b/circuits/sonobe/grayscale_step.compile_log index 1ecdc47..382300f 100644 --- a/circuits/sonobe/grayscale_step.compile_log +++ b/circuits/sonobe/grayscale_step.compile_log @@ -1,11 +1,11 @@ -template instances: 165 -non-linear constraints: 122952 +template instances: 87 +non-linear constraints: 168960 linear constraints: 0 public inputs: 2 private inputs: 256 public outputs: 2 -wires: 120395 -labels: 261169 +wires: 166403 +labels: 384655 Written successfully: ./grayscale_step.r1cs Written successfully: ./grayscale_step_js/grayscale_step.wasm Everything went okay diff --git a/circuits/sonobe/hash_step.compile_log b/circuits/sonobe/hash_step.compile_log index 9cc26b7..61eba46 100644 --- a/circuits/sonobe/hash_step.compile_log +++ b/circuits/sonobe/hash_step.compile_log @@ -1,11 +1,11 @@ -template instances: 154 -non-linear constraints: 7716 +template instances: 76 +non-linear constraints: 30720 linear constraints: 0 public inputs: 1 private inputs: 128 public outputs: 1 -wires: 7846 -labels: 37463 +wires: 30850 +labels: 99206 Written successfully: ./hash_step.r1cs Written successfully: ./hash_step_js/hash_step.wasm Everything went okay diff --git a/circuits/sonobe/resize_step.compile_log b/circuits/sonobe/resize_step.compile_log index c1c30d0..2a6e7fc 100644 --- a/circuits/sonobe/resize_step.compile_log +++ b/circuits/sonobe/resize_step.compile_log @@ -1,11 +1,11 @@ -template instances: 164 -non-linear constraints: 245904 +template instances: 85 +non-linear constraints: 337920 linear constraints: 0 public inputs: 2 private inputs: 512 (none belong to witness) public outputs: 2 -wires: 238227 -labels: 597849 +wires: 330243 +labels: 844818 Written successfully: ./resize_step.r1cs Written successfully: ./resize_step_js/resize_step.wasm Everything went okay diff --git a/circuits/sonobe/sharpness_step.compile_log b/circuits/sonobe/sharpness_step.compile_log index 57dc447..1fd772e 100644 --- a/circuits/sonobe/sharpness_step.compile_log +++ b/circuits/sonobe/sharpness_step.compile_log @@ -1,11 +1,11 @@ -template instances: 172 -non-linear constraints: 329910 +template instances: 94 +non-linear constraints: 421926 linear constraints: 0 public inputs: 4 private inputs: 512 (128 belong to witness) public outputs: 4 -wires: 314553 -labels: 805388 +wires: 406569 +labels: 1052360 Written successfully: ./sharpness_step.r1cs Written successfully: ./sharpness_step_js/sharpness_step.wasm Everything went okay diff --git a/circuits/src/utils/hashers.circom b/circuits/src/utils/hashers.circom index 300a784..7ac6182 100644 --- a/circuits/src/utils/hashers.circom +++ b/circuits/src/utils/hashers.circom @@ -1,3 +1,5 @@ +// Mini-library exposing various hasher templates. They impement Poseidon hashing for different input types. + pragma circom 2.0.0; include "../../node_modules/circomlib/circuits/poseidon.circom"; @@ -12,50 +14,109 @@ template PairHasher() { hash <== hasher.out; } -// Compute Poseidon hash of an array of values using a chunk size of 8. -template ArrayHasher(length) { - signal input array[length]; +// Compute Poseidon hash of an array of values. +template ArrayHasher(LENGTH) { + signal input array[LENGTH]; + signal output hash; + hash <== _LinearFoldHasher(LENGTH)(array); +// hash <== _WindowFoldHasher(LENGTH, 8)(array); +// hash <== _MerkleHasher(LENGTH, 8)(array); +} + +// Compute Poseidon hash of an array by folding the it *one element at a time*. +template _LinearFoldHasher(LENGTH) { + signal input array[LENGTH]; + signal output hash; + + signal intermediate_hash[LENGTH-1]; + + intermediate_hash[0] <== PairHasher()(array[0], array[1]); + for(var i = 1; i < LENGTH-1; i++) { + intermediate_hash[i] <== PairHasher()(intermediate_hash[i-1], array[i+1]); + } + + hash <== intermediate_hash[LENGTH-2]; +} + +// Compute Poseidon hash of an array by folding it with a *window of size `WINDOW_SIZE`*. +template _WindowFoldHasher(LENGTH, WINDOW_SIZE) { + signal input array[LENGTH]; signal output hash; - if (length == 1) { + var numRounds = (LENGTH + WINDOW_SIZE - 1) \ WINDOW_SIZE; + + signal intermediateHashes[numRounds]; + + // Process the first window + var firstWindowSize = (LENGTH < WINDOW_SIZE) ? LENGTH : WINDOW_SIZE; + component firstHasher = Poseidon(firstWindowSize); + for (var i = 0; i < firstWindowSize; i++) { + firstHasher.inputs[i] <== array[i]; + } + intermediateHashes[0] <== firstHasher.out; + + // Process subsequent windows + var processed = firstWindowSize; + component hashers[numRounds - 1]; + for (var foldRound = 0; foldRound < numRounds - 1; foldRound++) { + var remaining = LENGTH - processed; + var currentWindowSize = (remaining < WINDOW_SIZE - 1) ? remaining : WINDOW_SIZE - 1; + + hashers[foldRound] = Poseidon(currentWindowSize + 1); + hashers[foldRound].inputs[0] <== intermediateHashes[foldRound]; + for (var i = 0; i < currentWindowSize; i++) { + hashers[foldRound].inputs[i + 1] <== array[processed + i]; + } + intermediateHashes[foldRound + 1] <== hashers[foldRound].out; + processed += currentWindowSize; + } + + hash <== intermediateHashes[numRounds - 1]; +} + +// Compute Poseidon hash of an array by computing `ARITY`-ary Merkle tree of hashes over it. +template _MerkleHasher(LENGTH, ARITY) { + signal input array[LENGTH]; + signal output hash; + + var fullChunks = LENGTH \ ARITY; + var remainingElements = LENGTH % ARITY; + var chunks = fullChunks + (remainingElements > 0 ? 1 : 0); + + if (LENGTH == 1) { hash <== array[0]; } else { - var chunkSize = 8; + // Hashes of disjoint chunks of length `ARITY` (except possibly the last one, which might be shorter). + signal chunkOutputs[chunks]; - var fullChunks = length \ chunkSize; + // Handle full chunks. component fullHashers[fullChunks]; for (var i = 0; i < fullChunks; i++) { - fullHashers[i] = Poseidon(chunkSize); - for (var j = 0; j < chunkSize; j++) { - fullHashers[i].inputs[j] <== array[i * chunkSize + j]; + fullHashers[i] = Poseidon(ARITY); + for (var j = 0; j < ARITY; j++) { + fullHashers[i].inputs[j] <== array[i * ARITY + j]; } + chunkOutputs[i] <== fullHashers[i].out; } - if (length % chunkSize == 0) { - component nextRound = ArrayHasher(fullChunks); - for (var i = 0; i < fullChunks; i++) { - nextRound.array[i] <== fullHashers[i].out; + // Handle remaining elements (if any). + if (remainingElements > 0) { + component partialHasher = Poseidon(remainingElements); + for (var i = 0; i < remainingElements; i++) { + partialHasher.inputs[i] <== array[fullChunks * ARITY + i]; } - hash <== nextRound.hash; - } else { - component partialHasher = Poseidon(length % chunkSize); - for (var i = 0; i < length % chunkSize; i++) { - partialHasher.inputs[i] <== array[fullChunks * chunkSize + i]; - } - component nextRound = ArrayHasher(fullChunks + 1); - for (var i = 0; i < fullChunks; i++) { - nextRound.array[i] <== fullHashers[i].out; - } - nextRound.array[fullChunks] <== partialHasher.out; - hash <== nextRound.hash; + chunkOutputs[fullChunks] <== partialHasher.out; } + + // Recursively hash the chunk hashes. + hash <== _MerkleHasher(chunks, ARITY)(chunkOutputs); } } // Compute Poseidon hash of a single value and an array of values. -template HeadTailHasher(tailLength) { - signal input head, tail[tailLength]; +template HeadTailHasher(TAIL_LENGTH) { + signal input head, tail[TAIL_LENGTH]; signal output hash; - hash <== PairHasher()(head, ArrayHasher(tailLength)(tail)); + hash <== PairHasher()(head, ArrayHasher(TAIL_LENGTH)(tail)); }