refactor AssertBytes (#143)

Co-authored-by: 0xturboblitz <florent.tavernier@gmail.com>
This commit is contained in:
turnoffthiscomputer
2025-02-19 19:46:06 +01:00
committed by GitHub
parent 99168a45fe
commit 5534b7a91a
5 changed files with 33 additions and 14 deletions

View File

@@ -68,6 +68,9 @@ template DSC(
signal input path[nLevels];
signal input siblings[nLevels];
// assert only bytes are used in raw_csca
AssertBytes(MAX_CSCA_LENGTH)(raw_csca);
// first, compute raw_dsc_actual_length
// by getting the values of the last 4 bytes of the padded length
// cf sha padding

View File

@@ -92,6 +92,9 @@ template REGISTER(
signal input secret;
// assert only bytes are used in raw_dsc
AssertBytes(MAX_DSC_LENGTH)(raw_dsc);
// check dsc_pubKey_actual_size is at least the minimum key length
signal dsc_pubKey_actual_size_in_range <== GreaterEqThan(12)([
dsc_pubKey_actual_size,

View File

@@ -61,6 +61,7 @@ template PackBytesAndPoseidon(k) {
signal packed[packed_length] <== PackBytes(k)(in);
signal output out <== CustomHasher(packed_length)(packed);
}
/// @title AssertBytes
/// @notice Asserts that every element in the input array is a valid byte (i.e., less than 256).
/// @param k The number of elements in the input array.
@@ -68,21 +69,10 @@ template PackBytesAndPoseidon(k) {
/// @dev This template uses a chain of LessThan components to check that each byte is below 256. The results are cumulatively multiplied in checkArray, and the final constraint (checkArray[k-1] === 1) enforces that all bytes meet the condition.
template AssertBytes(k) {
signal input in[k];
signal checkArray[k];
component lessThan256[k];
component num2bits[k];
for (var i = 0; i < k; i++) {
if (i == 0) {
lessThan256[i] = LessThan(8);
lessThan256[i].in[0] <== in[i];
lessThan256[i].in[1] <== 256;
checkArray[i] <== lessThan256[i].out;
} else {
lessThan256[i] = LessThan(8);
lessThan256[i].in[0] <== in[i];
lessThan256[i].in[1] <== 256;
checkArray[i] <== lessThan256[i].out * checkArray[i-1];
}
num2bits[i] = Num2Bits(8);
num2bits[i].in <== in[i];
}
checkArray[k-1] === 1;
}

View File

@@ -282,5 +282,17 @@ testSuite.forEach(({ sigAlg, hashFunction, domainParameter, keyLength }) => {
expect(error.message).to.include('Assert Failed');
}
});
it('should fail if raw_csca has a signal that is longer than a byte', async function () {
try {
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
tamperedInputs.raw_csca[0] = (parseInt(tamperedInputs.raw_csca[0], 10) + 256).toString();
console.log(tamperedInputs.raw_csca);
await circuit.calculateWitness(tamperedInputs);
expect.fail('Expected an error but none was thrown.');
} catch (error: any) {
expect(error.message).to.include('Assert Failed');
}
});
});
});

View File

@@ -261,6 +261,17 @@ testSuite.forEach(
expect(nullifierTampered).to.equal(nullifierValid);
expect(commitmentTampered).to.not.be.equal(commitmentValid);
});
it('should fail if raw_dsc has a signal that is longer than a byte', async function () {
try {
const tamperedInputs = JSON.parse(JSON.stringify(inputs));
tamperedInputs.raw_dsc[0] = (parseInt(tamperedInputs.raw_dsc[0], 10) + 256).toString();
await circuit.calculateWitness(tamperedInputs);
expect.fail('Expected an error but none was thrown.');
} catch (error: any) {
expect(error.message).to.include('Assert Failed');
}
});
});
}
);