Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ res
src/solidity/cache
src/solidity/out
src/solidity/broadcast
src/solidity/zkpassport-packages/
# Ignore the anvil deployment file
src/solidity/deployments/deployment-31337.json
src/solidity/snapshots
src/ts/tests/fixtures/zkr/keypairs
output-fixtures
settings.json

src/noir/lib/facematch/src/android/tests.nr
src/noir/bin/facematch/android/**/src/tests.nr
src/noir/bin/facematch/android/**/src/tests.nr
4 changes: 2 additions & 2 deletions src/solidity/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ script/bash/update-roots.sh
cd $SCRIPT_DIR

# Run the tests
forge test --rpc-url http://localhost:${PORT} -vv
forge test --rpc-url http://localhost:${PORT} -vv "${@:2}"

# Kill the anvil process
lsof -ti:${PORT} | xargs kill -9
Expand All @@ -67,4 +67,4 @@ echo "Tests completed successfully"
# If the tests were run based off a fresh clone of the zkpassport-packages repo, remove it
if [ "$LOCAL_DIR" = "null" ]; then
rm -rf zkpassport-packages
fi
fi
3 changes: 3 additions & 0 deletions src/solidity/snapshots/VerifierTest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"UltraHonkVerifier verify": "1828340"
}
14 changes: 14 additions & 0 deletions src/solidity/snapshots/ZKPassportVerifierTest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"ZKPassportVerifier enforceSanctionsRoot": "47917",
"ZKPassportVerifier getBoundData": "75146",
"ZKPassportVerifier getDisclosedData": "40969",
"ZKPassportVerifier isAgeAboveOrEqual": "35853",
"ZKPassportVerifier isBirthdateBeforeOrEqual": "21943",
"ZKPassportVerifier isExpiryDateAfterOrEqual": "33812",
"ZKPassportVerifier isFaceMatchVerified": "32925",
"ZKPassportVerifier isIssuingCountryIn": "206685",
"ZKPassportVerifier isIssuingCountryOut": "204662",
"ZKPassportVerifier isNationalityIn": "203829",
"ZKPassportVerifier test_VerifyAllSubproofsProof1": "1882907",
"ZKPassportVerifier test_VerifyValidProof": "1879814"
}
43 changes: 26 additions & 17 deletions src/solidity/src/ZKPassportVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ contract ZKPassportVerifier {
}

function checkDate(
bytes32[] memory publicInputs,
bytes32[] calldata publicInputs,
uint256 validityPeriodInSeconds
) internal view returns (bool) {
uint256 currentDateTimeStamp = uint256(publicInputs[PublicInput.CURRENT_DATE_INDEX]);
Expand Down Expand Up @@ -464,7 +464,7 @@ contract ZKPassportVerifier {
}

function isCountryInOrOut(
string[] memory countryList,
string[] calldata countryList,
ProofType proofType,
Commitments calldata commitments
) private pure returns (bool) {
Expand All @@ -487,7 +487,7 @@ contract ZKPassportVerifier {
* @return True if the nationality is in the list of countries, false otherwise
*/
function isNationalityIn(
string[] memory countryList,
string[] calldata countryList,
Commitments calldata commitments
) public pure returns (bool) {
return isCountryInOrOut(countryList, ProofType.NATIONALITY_INCLUSION, commitments);
Expand All @@ -500,7 +500,7 @@ contract ZKPassportVerifier {
* @return True if the issuing country is in the list of countries, false otherwise
*/
function isIssuingCountryIn(
string[] memory countryList,
string[] calldata countryList,
Commitments calldata commitments
) public pure returns (bool) {
return isCountryInOrOut(countryList, ProofType.ISSUING_COUNTRY_INCLUSION, commitments);
Expand All @@ -514,7 +514,7 @@ contract ZKPassportVerifier {
* @return True if the nationality is not in the list of countries, false otherwise
*/
function isNationalityOut(
string[] memory countryList,
string[] calldata countryList,
Commitments calldata commitments
) public pure returns (bool) {
return isCountryInOrOut(countryList, ProofType.NATIONALITY_EXCLUSION, commitments);
Expand All @@ -528,7 +528,7 @@ contract ZKPassportVerifier {
* @return True if the issuing country is not in the list of countries, false otherwise
*/
function isIssuingCountryOut(
string[] memory countryList,
string[] calldata countryList,
Commitments calldata commitments
) public pure returns (bool) {
return isCountryInOrOut(countryList, ProofType.ISSUING_COUNTRY_EXCLUSION, commitments);
Expand Down Expand Up @@ -593,30 +593,39 @@ contract ZKPassportVerifier {
// What we call scope internally is derived from the domain
bytes32 scopeHash = StringUtils.isEmpty(domain)
? bytes32(0)
: sha256(abi.encodePacked(domain)) >> 8;
: sha256(bytes(domain)) >> 8;
// What we call the subscope internally is the scope specified
// manually in the SDK
bytes32 subscopeHash = StringUtils.isEmpty(scope)
? bytes32(0)
: sha256(abi.encodePacked(scope)) >> 8;
: sha256(bytes(scope)) >> 8;
return publicInputs[PublicInput.SCOPE_INDEX] == scopeHash && publicInputs[PublicInput.SUBSCOPE_INDEX] == subscopeHash;
}

function verifyCommittedInputs(
bytes32[] memory paramCommitments,
bytes32[] calldata paramCommitments,
Commitments calldata commitments
) internal pure {
) internal view {
uint256 offset = 0;
for (uint256 i = 0; i < commitments.committedInputCounts.length; i++) {
// One byte is dropped inside the circuit as BN254 is limited to 254 bits
bytes32 calculatedCommitment = sha256(
abi.encodePacked(commitments.committedInputs[offset:offset + commitments.committedInputCounts[i]])
) >> 8;
uint[] calldata counts = commitments.committedInputCounts;
bytes calldata inputs = commitments.committedInputs;
for (uint256 i = 0; i < counts.length; i++) {
uint count;
bytes32 calculatedCommitment;
assembly ("memory-safe") {
count := calldataload(add(counts.offset, shl(5, i)))
calldatacopy(mload(0x40), add(inputs.offset, offset), count)
if iszero(staticcall(gas(), 0x02, mload(0x40), count, 0x00, 0x20)) {
revert(0, 0)
}
// One byte is dropped inside the circuit as BN254 is limited to 254 bits
calculatedCommitment := shr(8, mload(0x00))
}
require(calculatedCommitment == paramCommitments[i], "Invalid commitment");
offset += commitments.committedInputCounts[i];
offset += count;
}
// Check that all the committed inputs have been covered, otherwise something is wrong
require(offset == commitments.committedInputs.length, "Invalid committed inputs length");
require(offset == inputs.length, "Invalid committed inputs length");
}

function _getVerifier(bytes32 vkeyHash) internal view returns (address) {
Expand Down
45 changes: 30 additions & 15 deletions src/solidity/src/ultra-honk-verifiers/OuterCount13.sol
Original file line number Diff line number Diff line change
Expand Up @@ -711,60 +711,62 @@ library TranscriptLib {

// Pairing point object
for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
p.pairingPointObject[i] = bytesToFr(proof, boundary);
boundary += FIELD_ELEMENT_SIZE;
}
// Commitments
p.w1 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.w1 = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
p.w2 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.w2 = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
p.w3 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.w3 = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;

// Lookup / Permutation Helper Commitments
p.lookupReadCounts = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.lookupReadCounts = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
p.lookupReadTags = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.lookupReadTags = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
p.w4 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.w4 = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
p.lookupInverses = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.lookupInverses = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
p.zPerm = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.zPerm = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;

// Sumcheck univariates
for (uint256 i = 0; i < logN; i++) {
for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) {
p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
p.sumcheckUnivariates[i][j] = bytesToFr(proof, boundary);
boundary += FIELD_ELEMENT_SIZE;
}
}
// Sumcheck evaluations
for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) {
p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
p.sumcheckEvaluations[i] = bytesToFr(proof, boundary);
boundary += FIELD_ELEMENT_SIZE;
}

// Gemini
// Read gemini fold univariates
for (uint256 i = 0; i < logN - 1; i++) {
p.geminiFoldComms[i] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.geminiFoldComms[i] = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
}

// Read gemini a evaluations
for (uint256 i = 0; i < logN; i++) {
p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
p.geminiAEvaluations[i] = bytesToFr(proof, boundary);
boundary += FIELD_ELEMENT_SIZE;
}

// Shplonk
p.shplonkQ = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.shplonkQ = bytesToG1Point(proof, boundary);
boundary += GROUP_ELEMENT_SIZE;
// KZG
p.kzgQuotient = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
p.kzgQuotient = bytesToG1Point(proof, boundary);

require(boundary + GROUP_ELEMENT_SIZE <= proof.length);
}
}

Expand Down Expand Up @@ -1568,6 +1570,12 @@ function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
scalar = FrLib.fromBytes32(bytes32(proofSection));
}

function bytesToFr(bytes calldata proof, uint offset) pure returns (Fr scalar) {
assembly {
scalar := mod(calldataload(add(proof.offset, offset)), MODULUS)
}
}

// EC Point utilities
function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point memory point) {
point = Honk.G1Point({
Expand All @@ -1576,6 +1584,13 @@ function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point
});
}

function bytesToG1Point(bytes calldata proofSection, uint offset) pure returns (Honk.G1Point memory point) {
assembly ("memory-safe") {
mstore(point, mod(calldataload(add(proofSection.offset, offset)), Q))
mstore(add(point, 0x20), mod(calldataload(add(proofSection.offset, add(offset, 0x20))), Q))
}
}

function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) {
point.y = (Q - point.y) % Q;
return point;
Expand Down
Loading