Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full Multi-query support onchain #321

Draft
wants to merge 45 commits into
base: master
Choose a base branch
from

Conversation

daveroga
Copy link
Contributor

@daveroga daveroga commented Dec 3, 2024

Implement multi-query support similar to existing requests now in Universal Verifier.

  • Manage multi-query (Query) independently and in the same way we are managing Requests in ZKPVerifierBase now (setQuery, getQuery, …). Avoid ZKP and generalize methods in Requests. setRequest, getRequest, submitResponse, …
  • Change _proofs mapping from address user to uint256 userID to keep identifier of the user.
  • Create 2 mappings for managing link between userAddress and userID . In this first version 1 userID will have only 1 address? Review best approach or if we have to keep an array of addresses.
mapping(address userAddress => uint256 userID) _user_address_to_id;
mapping(unit256 userID => address userAddress) _id_to_user_address; // check address[] ?
  • Manage Auth in specific type of requests. Auth requests.
requestId. 32 bytes (in Big Endian): 31-0x00(not used), 30-0x01(requestType), 29..0 hash calculated Id,

For requestType:
   - 0x00 - regular request
   - 0x01 - auth request
  • Define challenge based on the ethereum address in this first version
  • Review to reuse same Auth between requests
  • Figure out linkID between the Requests and Auth of the same Query.
  • Consider that more than one type of auth may be available there for specific multiRequest. And each of the multiRequests should define it’s own set of valid auth along with requests.
  • RequestId change from uint64 to uint256.

Link to Tech Spec for changes: https://www.notion.so/privado-id/Multi-query-Tech-Spec-13d4f86a875180e68fc8e3fa5362805e

@coveralls
Copy link

coveralls commented Dec 3, 2024

Pull Request Test Coverage Report for Build 12543564150

Details

  • 239 of 299 (79.93%) changed or added relevant lines in 12 files are covered.
  • 2 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-1.8%) to 82.269%

Changes Missing Coverage Covered Lines Changed/Added Lines %
contracts/validators/CredentialAtomicQueryV3Validator.sol 12 13 92.31%
contracts/verifiers/EmbeddedVerifier.sol 7 8 87.5%
contracts/verifiers/ValidatorWhitelist.sol 12 13 92.31%
contracts/validators/AuthV2Validator.sol 0 7 0.0%
contracts/validators/EthIdentityValidator.sol 0 16 0.0%
contracts/verifiers/Verifier.sol 150 184 81.52%
Files with Coverage Reduction New Missed Lines %
contracts/validators/AuthV2Validator.sol 1 0.0%
contracts/validators/CredentialAtomicQueryValidatorBase.sol 1 76.39%
Totals Coverage Status
Change from base Build 12413543528: -1.8%
Covered Lines: 1121
Relevant Lines: 1273

💛 - Coveralls

@daveroga daveroga force-pushed the PID-2709-full-multi-query-support-on-chain branch from b70f050 to a02592c Compare December 5, 2024 11:33
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
Copy link
Collaborator

@AndriianChestnykh AndriianChestnykh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good enough to discuss interface finalisation.
A few comments but not the full code check which is still to early to do

contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
contracts/verifiers/UniversalVerifierMultiQuery.sol Outdated Show resolved Hide resolved
Copy link
Collaborator

@AndriianChestnykh AndriianChestnykh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't completed review of all the files. However, these feedback is what I have now.

*/
function verify(
bytes calldata proof,
bytes calldata data,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename data to param maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to params in both IRequestValidator and IAuthValidator

Comment on lines 41 to 53
/**
* @dev Get the group ID of the request query data.
* @param params Request query data of the credential to verify.
* @return Group ID of the request query data.
*/
function getGroupID(bytes calldata params) external view returns (uint256);

/**
* @dev Get the verifier ID of the request query data.
* @param params Request query data of the credential to verify.
* @return Verifier ID encoded in the request query data.
*/
function getVerifierId(bytes calldata params) external view returns (uint256);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we introduce this method instead of those two?
function getGroupID(bytes calldata params) external view returns (uint256 groupID, uint256 verifierID);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created

    struct RequestParams {
        uint256 groupID;
        uint256 verifierID;
    }

function getRequestParams(bytes calldata params) external view returns (RequestParams memory);

* @param queryId The ID of the query
* @param query The query data
*/
function setQuery(uint256 queryId, Query calldata query) external;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already queryId inside the Query struct, so no reason to put it separatelly

struct Proof {
bool isVerified;
mapping(string key => uint256 inputValue) storageFields;
string validatorVersion;
uint256 blockNumber;
// TODO: discuss if we need this field
// uint256 blockNumber;
uint256 blockTimestamp;
mapping(string key => bytes) metadata;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mapping(string key => bytes) metadata; is not used anywhere, so let's remove it for now and use uint256[46] __gap instead

uint256 blockTimestamp;
// This empty reserved space is put in place to allow future versions
// (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps)
uint256[45] __gap;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint256[46] __gap is better for round number of slots (quals to 50). Not critical but good to have

Comment on lines +36 to 46
super.setRequests(singleRequests, groupedRequests);
for (uint256 i = 0; i < singleRequests.length; i++) {
_setRequestOwner(singleRequests[i].requestId, _msgSender());
}

for (uint256 i = 0; i < groupedRequests.length; i++) {
for (uint256 j = 0; j < groupedRequests[i].requests.length; j++) {
_setRequestOwner(groupedRequests[i].requests[j].requestId, _msgSender());
}
}
}
Copy link
Collaborator

@AndriianChestnykh AndriianChestnykh Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe overriding _setRequest and adding _setRequestOwner(singleRequests[i].requestId, _msgSender()); to its logic may help avoid these two cycles

Comment on lines +111 to 134
) public override(RequestOwnership, ValidatorWhitelist, Verifier) {
super.setRequests(singleRequests, groupedRequests);

for (uint256 i = 0; i < singleRequests.length; i++) {
emit RequestSet(
singleRequests[i].requestId,
_msgSender(),
singleRequests[i].metadata,
address(singleRequests[i].validator),
singleRequests[i].params
);
}

for (uint256 i = 0; i < groupedRequests.length; i++) {
for (uint256 j = 0; j < groupedRequests[i].requests.length; j++) {
emit RequestSet(
groupedRequests[i].requests[j].requestId,
_msgSender(),
groupedRequests[i].requests[j].metadata,
address(groupedRequests[i].requests[j].validator),
groupedRequests[i].requests[j].params
);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same, try to override the _setRequest method itself with additional functionality

Comment on lines +180 to +193
super.submitResponse(authResponses, singleResponses, groupedResponses, crossChainProofs);
for (uint256 i = 0; i < authResponses.length; i++) {
emit AuthResponseSubmitted(authResponses[i].authType, _msgSender());
}
}

/// @dev Verifies a ZKP response without updating any proof status
/// @param requestId The ID of the ZKP request
/// @param inputs The public inputs for the proof
/// @param a The first component of the proof
/// @param b The second component of the proof
/// @param c The third component of the proof
/// @param sender The sender on behalf of which the proof is done
function verifyZKPResponse(
uint64 requestId,
uint256[] memory inputs,
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
address sender
)
public
override(RequestDisableable, ValidatorWhitelist, ZKPVerifierBase)
returns (ICircuitValidator.KeyToInputIndex[] memory)
{
return super.verifyZKPResponse(requestId, inputs, a, b, c, sender);
for (uint256 i = 0; i < singleResponses.length; i++) {
emit ResponseSubmitted(singleResponses[i].requestId, _msgSender());
}

for (uint256 i = 0; i < groupedResponses.length; i++) {
for (uint256 j = 0; j < groupedResponses[i].responses.length; j++) {
emit ResponseSubmitted(groupedResponses[i].responses[j].requestId, _msgSender());
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same note regarding overriding. Try to avoid the loops

Comment on lines +48 to +62
for (uint256 i = 0; i < singleRequests.length; i++) {
IRequestValidator validator = singleRequests[i].validator;
if (!isWhitelistedValidator(validator)) {
revert ValidatorIsNotWhitelisted(address(validator));
}
}
}

/// @dev Verifies a ZKP response without updating any proof status
/// @param requestId The ID of the ZKP request
/// @param inputs The public inputs for the proof
/// @param a The first component of the proof
/// @param b The second component of the proof
/// @param c The third component of the proof
/// @param sender The sender on behalf of which the proof is done
function verifyZKPResponse(
uint64 requestId,
uint256[] memory inputs,
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
address sender
) public virtual override returns (ICircuitValidator.KeyToInputIndex[] memory) {
ICircuitValidator validator = getZKPRequest(requestId).validator;
require(isWhitelistedValidator(validator), "Validator is not whitelisted");
return super.verifyZKPResponse(requestId, inputs, a, b, c, sender);
for (uint256 i = 0; i < groupedRequests.length; i++) {
for (uint256 j = 0; j < groupedRequests[i].requests.length; j++) {
IRequestValidator validator = groupedRequests[i].requests[j].validator;
if (!isWhitelistedValidator(validator)) {
revert ValidatorIsNotWhitelisted(address(validator));
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same. Try to avoid the loops

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we introduce breaking change. You may just remove this file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants