diff --git a/packages/circuits/helpers/substring-match.circom b/packages/circuits/helpers/substring-match.circom index b1143b6a..cb2e31cb 100644 --- a/packages/circuits/helpers/substring-match.circom +++ b/packages/circuits/helpers/substring-match.circom @@ -2,6 +2,7 @@ pragma circom 2.1.6; include "circomlib/circuits/comparators.circom"; include "circomlib/circuits/mux1.circom"; +include "../utils/hash.circom"; /// @title SubstringMatch /// @notice This template verifies if a given substring exists within a larger string at a specified index @@ -15,9 +16,21 @@ include "circomlib/circuits/mux1.circom"; /// @output isValid A signal that is 1 if the substring matches at the given index, 0 otherwise template SubstringMatch(maxLength, maxSubstringLength) { signal input in[maxLength]; - signal input startIndex; signal input revealedString[maxSubstringLength]; - signal input r; + signal input startIndex; + + // Derive r from the inputs + signal r; + component rHasher; + rHasher = PoseidonModular(maxLength + maxSubstringLength + 1); + rHasher.in[0] <== startIndex; + for (var i = 0; i < maxSubstringLength; i++) { + rHasher.in[i + 1] <== revealedString[i]; + } + for (var i = 0; i < maxLength; i++) { + rHasher.in[i + maxSubstringLength + 1] <== in[i]; + } + r <== rHasher.out; // Check if each character in the revealed string is non-zero signal isNonZero[maxSubstringLength]; diff --git a/packages/circuits/tests/substring-match.test.ts b/packages/circuits/tests/substring-match.test.ts index 7ee83e9e..ad9174c9 100644 --- a/packages/circuits/tests/substring-match.test.ts +++ b/packages/circuits/tests/substring-match.test.ts @@ -24,8 +24,7 @@ describe('SubstringMatch', () => { const input = { in: padArray([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], 32), // "hello world" startIndex: 6, - revealedString: padArray([119, 111, 114, 108, 100], 16), // "world" - r: 69, // A prime number for the random linear combination + revealedString: padArray([119, 111, 114, 108, 100], 16), // "world" }; const witness = await circuit.calculateWitness(input); @@ -41,7 +40,6 @@ describe('SubstringMatch', () => { in: padArray([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], 32), // "hello world" startIndex: 6, revealedString: padArray([119, 111, 114, 108, 107], 16), // "worlk" (last character different) - r: 69, }; const witness = await circuit.calculateWitness(input); @@ -57,7 +55,6 @@ describe('SubstringMatch', () => { in: padArray([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], 32), // "hello world" startIndex: 0, revealedString: padArray([104, 101, 108, 108, 111], 16), // "hello" - r: 69, }; const witness = await circuit.calculateWitness(input); @@ -73,7 +70,6 @@ describe('SubstringMatch', () => { in: padArray([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], 32), // "hello world" startIndex: 7, revealedString: padArray([111, 114, 108, 100], 16), // "orld" - r: 69, }; const witness = await circuit.calculateWitness(input); @@ -89,7 +85,6 @@ describe('SubstringMatch', () => { in: padArray([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], 32), // "hello world" startIndex: 32, // Out of bounds (valid indices are 0-31) revealedString: padArray([100], 16), // "d" - r: 69, }; const witness = await circuit.calculateWitness(input);