fix: computing r by hashing inputs

This commit is contained in:
shreyas-londhe
2024-07-22 12:30:44 +05:30
parent 1ac147c007
commit 4e91fb206e
4 changed files with 80 additions and 5 deletions

View File

@@ -2,14 +2,15 @@ pragma circom 2.1.6;
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/mux1.circom";
include "../utils/hash.circom";
template RemoveSoftLineBreaks(maxLength) {
signal input encoded[maxLength];
signal input decoded[maxLength];
signal input r;
signal output is_valid;
// Helper signals
signal r;
signal processed[maxLength];
signal is_equals[maxLength];
signal is_cr[maxLength];
@@ -26,6 +27,16 @@ template RemoveSoftLineBreaks(maxLength) {
// Helper components
component mux_enc[maxLength];
// Deriving r from Poseidon hash
component r_hasher = PoseidonModular(2 * maxLength);
for (var i = 0; i < maxLength; i++) {
r_hasher.in[i] <== encoded[i];
}
for (var i = 0; i < maxLength; i++) {
r_hasher.in[maxLength + i] <== decoded[i];
}
r <== r_hasher.out;
// Check for '=' (61 in ASCII)
for (var i = 0; i < maxLength; i++) {
is_equals[i] <== IsEqual()([encoded[i], 61]);

View File

@@ -54,7 +54,6 @@ describe('RemoveSoftLineBreaks', () => {
107,
...Array(21).fill(0),
],
r: 69,
};
const witness = await circuit.calculateWitness(input);
@@ -98,10 +97,9 @@ describe('RemoveSoftLineBreaks', () => {
114,
101,
97,
108,
108, // Changed last character
...Array(21).fill(0),
], // Changed last character
r: 69,
],
};
const witness = await circuit.calculateWitness(input);

View File

@@ -162,3 +162,25 @@ template AssertZeroPadding(maxArrayLen) {
lessThans[i].out * in[i] === 0;
}
}
/// @title Slice
/// @notice Extract a fixed portion of an array
/// @dev Unlike SelectSubArray, Slice uses compile-time known indices and doesn't pad the output
/// @dev Slice is more efficient for fixed ranges, while SelectSubArray offers runtime flexibility
/// @param n The length of the input array
/// @param start The starting index of the slice (inclusive)
/// @param end The ending index of the slice (exclusive)
/// @input in The input array of length n
/// @output out The sliced array of length (end - start)
template Slice(n, start, end) {
assert(n >= end);
assert(start >= 0);
assert(end >= start);
signal input in[n];
signal output out[end - start];
for (var i = start; i < end; i++) {
out[i - start] <== in[i];
}
}

View File

@@ -1,5 +1,7 @@
pragma circom 2.1.6;
include "circomlib/circuits/poseidon.circom";
include "./array.circom";
/// @title PoseidonLarge
/// @notice Circuit to calculate Poseidon hash of inputs more than 16
@@ -36,3 +38,45 @@ template PoseidonLarge(bitsPerChunk, chunkSize) {
out <== Poseidon(halfChunkSize)(poseidonInput);
}
/// @title PoseidonModular
/// @notice Circuit to calculate Poseidon hash of an arbitrary number of inputs
/// @notice Splits input into chunks of 16 elements (or less for the last chunk) and hashes them separately
/// @notice Then combines the chunk hashes using a binary tree structure
/// @param numElements Number of elements in the input array
/// @input 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] = Slice(numElements, start, end)(in);
chunk_hash = Poseidon(last_chunk_size)(last_chunk);
} else {
var chunk[16] = Slice(numElements, start, end)(in);
chunk_hash = Poseidon(16)(chunk);
}
if (i == 0) {
_out = chunk_hash;
} else {
_out = Poseidon(2)([_out, chunk_hash]);
}
}
out <== _out;
}