diff --git a/contracts/interfaces/ICircuitValidator.sol b/contracts/interfaces/ICircuitValidator.sol index fd7b145f..0ca06ca3 100644 --- a/contracts/interfaces/ICircuitValidator.sol +++ b/contracts/interfaces/ICircuitValidator.sol @@ -2,6 +2,11 @@ pragma solidity 0.8.16; interface ICircuitValidator { + struct KeyInputIndexPair { + string key; + uint256 inputIndex; + } + function verify( uint256[] memory inputs, uint256[2] memory a, @@ -14,5 +19,5 @@ interface ICircuitValidator { function inputIndexOf(string memory name) external view returns (uint256); - function getSpecialInputNumbers() external pure returns (uint256[] memory); + function getSpecialInputPairs() external pure returns (KeyInputIndexPair[] memory); } diff --git a/contracts/validators/CredentialAtomicQueryMTPValidator.sol b/contracts/validators/CredentialAtomicQueryMTPValidator.sol index 36801165..58312c37 100644 --- a/contracts/validators/CredentialAtomicQueryMTPValidator.sol +++ b/contracts/validators/CredentialAtomicQueryMTPValidator.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.16; import {CredentialAtomicQueryValidator} from "./CredentialAtomicQueryValidator.sol"; import {IVerifier} from "../interfaces/IVerifier.sol"; +import {ICircuitValidator} from "../interfaces/ICircuitValidator.sol"; contract CredentialAtomicQueryMTPValidator is CredentialAtomicQueryValidator { /** @@ -80,10 +81,10 @@ contract CredentialAtomicQueryMTPValidator is CredentialAtomicQueryValidator { return params; } - function getSpecialInputNumbers() public pure override returns (uint256[] memory) { - uint256[] memory specialInputNumbers = new uint256[](2); - specialInputNumbers[0] = 1; //UserID - specialInputNumbers[1] = 10; //Timestamp - return specialInputNumbers; + function getSpecialInputPairs() public pure override returns (ICircuitValidator.KeyInputIndexPair[] memory) { + ICircuitValidator.KeyInputIndexPair[] memory pairs = new ICircuitValidator.KeyInputIndexPair[](2); + pairs[0] = ICircuitValidator.KeyInputIndexPair({key: "userID", inputIndex: 1}); + pairs[1] = ICircuitValidator.KeyInputIndexPair({key: "timestamp", inputIndex: 10}); + return pairs; } } diff --git a/contracts/validators/CredentialAtomicQuerySigValidator.sol b/contracts/validators/CredentialAtomicQuerySigValidator.sol index 0101c915..87438613 100644 --- a/contracts/validators/CredentialAtomicQuerySigValidator.sol +++ b/contracts/validators/CredentialAtomicQuerySigValidator.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.16; import {CredentialAtomicQueryValidator} from "./CredentialAtomicQueryValidator.sol"; import {IVerifier} from "../interfaces/IVerifier.sol"; +import {ICircuitValidator} from "../interfaces/ICircuitValidator.sol"; contract CredentialAtomicQuerySigValidator is CredentialAtomicQueryValidator { /** @@ -80,10 +81,10 @@ contract CredentialAtomicQuerySigValidator is CredentialAtomicQueryValidator { return params; } - function getSpecialInputNumbers() public pure override returns (uint256[] memory) { - uint256[] memory specialInputNumbers = new uint256[](2); - specialInputNumbers[0] = 1; //UserID - specialInputNumbers[1] = 10; //Timestamp - return specialInputNumbers; + function getSpecialInputPairs() public pure override returns (ICircuitValidator.KeyInputIndexPair[] memory) { + ICircuitValidator.KeyInputIndexPair[] memory pairs = new ICircuitValidator.KeyInputIndexPair[](2); + pairs[0] = ICircuitValidator.KeyInputIndexPair({key: "userID", inputIndex: 1}); + pairs[1] = ICircuitValidator.KeyInputIndexPair({key: "timestamp", inputIndex: 10}); + return pairs; } } diff --git a/contracts/validators/CredentialAtomicQueryV3Validator.sol b/contracts/validators/CredentialAtomicQueryV3Validator.sol index 6ab6a687..c59efdee 100644 --- a/contracts/validators/CredentialAtomicQueryV3Validator.sol +++ b/contracts/validators/CredentialAtomicQueryV3Validator.sol @@ -5,6 +5,7 @@ import {CredentialAtomicQueryValidator} from "./CredentialAtomicQueryValidator.s import {IVerifier} from "../interfaces/IVerifier.sol"; import {PrimitiveTypeUtils} from "../lib/PrimitiveTypeUtils.sol"; import {GenesisUtils} from "../lib/GenesisUtils.sol"; +import {ICircuitValidator} from "../interfaces/ICircuitValidator.sol"; /** * @dev CredentialAtomicQueryV3 validator @@ -226,15 +227,15 @@ contract CredentialAtomicQueryV3Validator is CredentialAtomicQueryValidator { return pubSignals; } - function getSpecialInputNumbers() public pure override returns (uint256[] memory) { - uint256[] memory specialInputNumbers = new uint256[](7); - specialInputNumbers[0] = 1; //UserID - specialInputNumbers[1] = 4; //LinkID - specialInputNumbers[2] = 5; //Nullifier - specialInputNumbers[3] = 6; //OperatorOutput - specialInputNumbers[4] = 14; //Timestamp - specialInputNumbers[5] = 15; //VerifierID - specialInputNumbers[6] = 16; //NullifierSessionID - return specialInputNumbers; + function getSpecialInputPairs() public pure override returns (ICircuitValidator.KeyInputIndexPair[] memory) { + ICircuitValidator.KeyInputIndexPair[] memory pairs = new ICircuitValidator.KeyInputIndexPair[](2); + pairs[0] = ICircuitValidator.KeyInputIndexPair({key: "userID", inputIndex: 1}); + pairs[1] = ICircuitValidator.KeyInputIndexPair({key: "linkID", inputIndex: 4}); + pairs[2] = ICircuitValidator.KeyInputIndexPair({key: "nullifier", inputIndex: 5}); + pairs[3] = ICircuitValidator.KeyInputIndexPair({key: "operatorOutput", inputIndex: 6}); + pairs[4] = ICircuitValidator.KeyInputIndexPair({key: "timestamp", inputIndex: 14}); + pairs[5] = ICircuitValidator.KeyInputIndexPair({key: "verifierID", inputIndex: 15}); + pairs[6] = ICircuitValidator.KeyInputIndexPair({key: "nullifierSessionID", inputIndex: 16}); + return pairs; } } diff --git a/contracts/validators/CredentialAtomicQueryValidator.sol b/contracts/validators/CredentialAtomicQueryValidator.sol index 9468d476..953bc472 100644 --- a/contracts/validators/CredentialAtomicQueryValidator.sol +++ b/contracts/validators/CredentialAtomicQueryValidator.sol @@ -263,5 +263,5 @@ abstract contract CredentialAtomicQueryValidator is OwnableUpgradeable, ICircuit } } - function getSpecialInputNumbers() public pure virtual returns (uint256[] memory); + function getSpecialInputPairs() public pure virtual returns (ICircuitValidator.KeyInputIndexPair[] memory); } diff --git a/contracts/verifiers/UniversalVerifier.sol b/contracts/verifiers/UniversalVerifier.sol index d6b3aec4..6a4b2cf1 100644 --- a/contracts/verifiers/UniversalVerifier.sol +++ b/contracts/verifiers/UniversalVerifier.sol @@ -13,10 +13,15 @@ import {ArrayUtils} from "../lib/ArrayUtils.sol"; /// @title Universal Verifier Contract /// @notice A contract to manage ZKP (Zero-Knowledge Proof) requests and proofs. contract UniversalVerifier is OwnableUpgradeable { + struct StorageField { + uint256 value; + bytes rawValue; // TODO provisioned with separate transactions + } + /// @dev Struct to store ZKP proof and associated data struct Proof { bool isProved; - uint256[] specialInputs; + mapping(string => StorageField) storageFields; bytes metadata; } @@ -197,8 +202,14 @@ contract UniversalVerifier is OwnableUpgradeable { /// @param user The user's address /// @param requestId The ID of the ZKP request /// @return The proof - function getProof(address user, uint64 requestId) public view returns (Proof memory) { - return _getMainStorage().proofs[user][requestId]; + // TODO finalize it + function getProofStorageItem(address user, uint64 requestId, string memory key) public view returns (uint256) { + return _getMainStorage().proofs[user][requestId].storageFields[key].value; + } + + struct KeyValuePair { + string key; + uint256 value; } /// @notice Submits a ZKP response and updates proof status @@ -213,6 +224,9 @@ contract UniversalVerifier is OwnableUpgradeable { uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c + // TODO add additional data and circuit id +// bytes calldata additionalData, +// string calldata circuitId ) public enabled(requestId) { address sender = _msgSender(); require( @@ -220,13 +234,15 @@ contract UniversalVerifier is OwnableUpgradeable { "validator is not set for this request id" ); - uint[] memory specialInputNumbers = _callVerifyWithSender(requestId, inputs, a, b, c, sender); - uint[] memory specialInputs = new uint[](specialInputNumbers.length); - for (uint i = 0; i < specialInputNumbers.length; i++) { - specialInputs[i] = inputs[specialInputNumbers[i]]; + ICircuitValidator.KeyInputIndexPair[] memory pairs = _callVerifyWithSender(requestId, inputs, a, b, c, sender); + for (uint256 i = 0; i < pairs.length; i++) { + _getMainStorage().proofs[sender][requestId].storageFields[pairs[i].key] = StorageField( + inputs[pairs[i].inputIndex], + "" + ); } - _getMainStorage().proofs[msg.sender][requestId] = Proof(true, specialInputs, ""); + _getMainStorage().proofs[msg.sender][requestId].isProved = true; emit ZKPResponseSubmitted(requestId, sender); } @@ -259,7 +275,7 @@ contract UniversalVerifier is OwnableUpgradeable { uint256[2][2] calldata b, uint256[2] calldata c, address sender - ) internal view returns (uint256[] memory) { + ) internal view returns (ICircuitValidator.KeyInputIndexPair[] memory) { IZKPVerifier.ZKPRequestExtended memory request = _getMainStorage().requests[ requestId ]; @@ -281,6 +297,6 @@ contract UniversalVerifier is OwnableUpgradeable { revert("Failed to verify proof without revert reason"); } } - return request.validator.getSpecialInputNumbers(); + return request.validator.getSpecialInputPairs(); } } diff --git a/test/verifier/universal-verifier.test.ts b/test/verifier/universal-verifier.test.ts index 609292a4..0d699afa 100644 --- a/test/verifier/universal-verifier.test.ts +++ b/test/verifier/universal-verifier.test.ts @@ -87,20 +87,16 @@ describe("ZKP Verifier", function () { .withArgs(0, signerAddress); await verifier.verifyZKPResponse(0, inputs, pi_a, pi_b, pi_c); - const [user] = await ethers.getSigners(); - const userAddress = await user.getAddress(); const requestId = 0; - let result = await verifier.getProofStatus(userAddress, requestId); + let result = await verifier.getProofStatus(signerAddress, requestId); expect(result).to.be.equal(true); - result = await verifier.getProofStatus(userAddress, requestId + 1); + result = await verifier.getProofStatus(signerAddress, requestId + 1); expect(result).to.be.equal(false); - result = await verifier.getProof(signerAddress, requestId); - - expect(result.isProved).to.be.equal(true); - expect(result.specialInputs[0]).to.be.equal(inputs[1]); // First special input is UserID - expect(result.specialInputs[1]).to.be.equal(inputs[10]); // Second special input is Timestamp - expect(result.metadata).to.be.equal("0x"); + expect(await verifier.getProofStorageItem(signerAddress, requestId, "userID")) + .to.equal("23148936466334350744548790012294489365207440754509988986684797708370051073"); + expect(await verifier.getProofStorageItem(signerAddress, requestId, "timestamp")) + .to.equal("1642074362"); }); it('Test getZKPRequests pagination', async () => {