Skip to content
Merged
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
103 changes: 69 additions & 34 deletions contracts/validators/CredentialAtomicQueryMTPValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
import {GenesisUtils} from "@iden3/contracts/lib/GenesisUtils.sol";
import {ICircuitValidator} from "@iden3/contracts/interfaces/ICircuitValidator.sol";
import {IVerifier} from "@iden3/contracts/interfaces/IVerifier.sol";
import {IState} from "@iden3/contracts/interfaces/IState.sol";
import {StateV2} from "@iden3/contracts/state/StateV2.sol";

contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValidator {
contract CredentialAtomicQueryMTPValidator is
OwnableUpgradeable,
ICircuitValidator
{
string constant CIRCUIT_ID = "credentialAtomicQueryMTPV2OnChain";
uint256 constant CHALLENGE_INDEX = 4;

IVerifier public verifier;
IState public state;
StateV2 public state;

uint256 public revocationStateExpirationTime;
uint256 public proofGenerationExpirationTime;
Expand All @@ -24,15 +27,22 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida
revocationStateExpirationTime = 1 hours;
proofGenerationExpirationTime = 1 hours;
verifier = IVerifier(_verifierContractAddr);
state = IState(_stateContractAddr);
state = StateV2(_stateContractAddr);
__Ownable_init();
}

function setRevocationStateExpirationTime(uint256 expirationTime) public onlyOwner {
function setRevocationStateExpirationTime(uint256 expirationTime)
public
onlyOwner
{
revocationStateExpirationTime = expirationTime;
}

function setProofGenerationExpirationTime(uint256 expirationTime) public virtual onlyOwner {
function setProofGenerationExpirationTime(uint256 expirationTime)
public
virtual
onlyOwner
{
proofGenerationExpirationTime = expirationTime;
}

Expand All @@ -52,9 +62,15 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida
uint256 queryHash
) external view returns (bool r) {
// verify that zkp is valid
require(verifier.verifyProof(a, b, c, inputs), "MTP proof is not valid");
require(
verifier.verifyProof(a, b, c, inputs),
"MTP proof is not valid"
);

require(inputs[2] == queryHash, "query hash does not match the requested one");
require(
inputs[2] == queryHash,
"query hash does not match the requested one"
);

// verify user states
uint256 gistRoot = inputs[5];
Expand All @@ -63,58 +79,77 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida
uint256 issuerClaimNonRevState = inputs[9];
uint256 proofGenerationTimestamp = inputs[10];

IState.GistRootInfo memory rootInfo = state.getGISTRootInfo(gistRoot);
StateV2.GistRootInfo memory rootInfo = state.getGISTRootInfo(gistRoot);

require(rootInfo.root == gistRoot, "Gist root state isn't in state contract");
require(
rootInfo.root == gistRoot,
"Gist root state isn't in state contract"
);

// 2. Issuer state must be registered in state contracts or be genesis
bool isIssuerStateGenesis = GenesisUtils.isGenesisState(issuerId, issuerClaimIdenState);
// Issuer issuance state must be registered in state contracts or be genesis
bool isIssuerStateGenesis = GenesisUtils.isGenesisState(
issuerId,
issuerClaimIdenState
);

if (!isIssuerStateGenesis) {
IState.StateInfo memory issuerStateInfo = state.getStateInfoByIdAndState(
issuerId, issuerClaimIdenState
StateV2.StateInfo memory issuerStateInfo = state
.getStateInfoByIdAndState(issuerId, issuerClaimIdenState);
require(
issuerId == issuerStateInfo.id,
"Issuer state doesn't exist in state contract"
);
require(issuerId == issuerStateInfo.id, "Issuer state doesn't exist in state contract");
}

IState.StateInfo memory issuerClaimNonRevStateInfo = state.getStateInfoById(issuerId);
// check if identity transited any state in contract
bool idExists = state.idExists(issuerId);

if (issuerClaimNonRevStateInfo.state == 0) {
// if identity didn't transit any state it must be genesis
if (!idExists) {
bool isIssuerRevocationStateGenesis = GenesisUtils.isGenesisState(
issuerId,
issuerClaimNonRevState
);
require(
GenesisUtils.isGenesisState(issuerId, issuerClaimNonRevState),
"Non-Revocation state isn't in state contract and not genesis"
isIssuerRevocationStateGenesis,
"Issuer revocation state doesn't exist in state contract and is not genesis "
);
} else {
// The non-empty state is returned, and it's not equal to the state that the user has provided.
if (issuerClaimNonRevStateInfo.state != issuerClaimNonRevState) {
StateV2.StateInfo memory issuerLatestStateInfo = state
.getStateInfoById(issuerId);
if (issuerLatestStateInfo.state != issuerClaimNonRevState) {
// Get the time of the latest state and compare it to the transition time of state provided by the user.
IState.StateInfo memory issuerClaimNonRevLatestStateInfo = state
.getStateInfoByIdAndState(issuerId,issuerClaimNonRevState);
StateV2.StateInfo memory issuerClaimNonRevStateInfo = state
.getStateInfoByIdAndState(issuerId, issuerClaimNonRevState);

if (
issuerClaimNonRevLatestStateInfo.id == 0 ||
issuerClaimNonRevLatestStateInfo.id != issuerId
issuerClaimNonRevStateInfo.id == 0 ||
issuerClaimNonRevStateInfo.id != issuerId
) {
revert("state in transition info contains invalid id");
}

if (issuerClaimNonRevLatestStateInfo.replacedAtTimestamp == 0) {
revert("Non-Latest state doesn't contain replacement information");
if (issuerClaimNonRevStateInfo.replacedAtTimestamp == 0) {
revert(
"Non-Latest state doesn't contain replacement information"
);
}

if (
block.timestamp - issuerClaimNonRevLatestStateInfo.replacedAtTimestamp >
block.timestamp -
issuerClaimNonRevStateInfo.replacedAtTimestamp >
revocationStateExpirationTime
) {
revert("Non-Revocation state of Issuer expired");
}

if (block.timestamp - proofGenerationTimestamp > proofGenerationExpirationTime) {
revert("Generated proof is outdated");
}
}
}

if (
block.timestamp - proofGenerationTimestamp >
proofGenerationExpirationTime
) {
revert("Generated proof is outdated");
}
return (true);
}
}
}
109 changes: 72 additions & 37 deletions contracts/validators/CredentialAtomicQuerySigValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
import {GenesisUtils} from "@iden3/contracts/lib/GenesisUtils.sol";
import {ICircuitValidator} from "@iden3/contracts/interfaces/ICircuitValidator.sol";
import {IVerifier} from "@iden3/contracts/interfaces/IVerifier.sol";
import {IState} from "@iden3/contracts/interfaces/IState.sol";
import {StateV2} from "@iden3/contracts/state/StateV2.sol";

contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValidator {
contract CredentialAtomicQuerySigValidator is
OwnableUpgradeable,
ICircuitValidator
{
string constant CIRCUIT_ID = "credentialAtomicQuerySigV2OnChain";
uint256 constant CHALLENGE_INDEX = 5;

IVerifier public verifier;
IState public state;
StateV2 public state;

uint256 public revocationStateExpirationTime;
uint256 public proofGenerationExpirationTime;
Expand All @@ -24,15 +27,22 @@ contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValida
revocationStateExpirationTime = 1 hours;
proofGenerationExpirationTime = 1 hours;
verifier = IVerifier(_verifierContractAddr);
state = IState(_stateContractAddr);
state = StateV2(_stateContractAddr);
__Ownable_init();
}

function setRevocationStateExpirationTime(uint256 expirationTime) public onlyOwner {
function setRevocationStateExpirationTime(uint256 expirationTime)
public
onlyOwner
{
revocationStateExpirationTime = expirationTime;
}

function setProofGenerationExpirationTime(uint256 expirationTime) public virtual onlyOwner {
function setProofGenerationExpirationTime(uint256 expirationTime)
public
virtual
onlyOwner
{
proofGenerationExpirationTime = expirationTime;
}

Expand All @@ -52,67 +62,92 @@ contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValida
uint256 queryHash
) external view returns (bool r) {
// verify that zkp is valid
require(verifier.verifyProof(a, b, c, inputs), "atomic query signature proof is not valid");
require(inputs[2] == queryHash, "query hash does not match the requested one");
require(
verifier.verifyProof(a, b, c, inputs),
"atomic query signature proof is not valid"
);
require(
inputs[2] == queryHash,
"query hash does not match the requested one"
);

uint256 issuerClaimAuthState = inputs[3];
uint256 gistRoot = inputs[6];
uint256 issuerId = inputs[7];
uint256 issuerClaimNonRevState = inputs[9];
uint256 proofGenerationTimestamp = inputs[10];

IState.GistRootInfo memory rootInfo = state.getGISTRootInfo(gistRoot);
StateV2.GistRootInfo memory rootInfo = state.getGISTRootInfo(gistRoot);

require(rootInfo.root == gistRoot, "Gist root state isn't in state contract");
require(
rootInfo.root == gistRoot,
"Gist root state isn't in state contract"
);

// 2. Issuer state must be registered in state contracts or be genesis
bool isIssuerStateGenesis = GenesisUtils.isGenesisState(issuerId, issuerClaimAuthState);
// Issuer auth claim issuance must be registered in state contracts or be genesis
bool isIssuerStateGenesis = GenesisUtils.isGenesisState(
issuerId,
issuerClaimAuthState
);

if (!isIssuerStateGenesis) {
IState.StateInfo memory issuerStateInfo = state.getStateInfoByIdAndState(
issuerId, issuerClaimAuthState
StateV2.StateInfo memory issuerStateInfo = state
.getStateInfoByIdAndState(issuerId, issuerClaimAuthState);
require(
issuerId == issuerStateInfo.id,
"Issuer state doesn't exist in state contract"
);
require(issuerId == issuerStateInfo.id, "Issuer state doesn't exist in state contract");
}

IState.StateInfo memory issuerClaimNonRevStateInfo = state.getStateInfoById(issuerId);

if (issuerClaimNonRevStateInfo.state == 0) {
// check if identity transited any state in contract
bool idExists = state.idExists(issuerId);

// if identity didn't transit any state it must be genesis
if (!idExists) {
bool isIssuerRevocationStateGenesis = GenesisUtils.isGenesisState(
issuerId,
issuerClaimNonRevState
);
require(
GenesisUtils.isGenesisState(issuerId, issuerClaimNonRevState),
"Non-Revocation state isn't in state contract and not genesis"
isIssuerRevocationStateGenesis,
"Issuer revocation state doesn't exist in state contract and is not genesis "
);
} else {
// The non-empty state is returned, and it's not equal to the state that the user has provided.
if (issuerClaimNonRevStateInfo.state != issuerClaimNonRevState) {
// Get the time of the latest state and compare it to the transition time of state provided by the user.
IState.StateInfo memory issuerClaimNonRevLatestStateInfo = state
.getStateInfoByIdAndState(issuerId, issuerClaimNonRevState);
StateV2.StateInfo memory issuerLatestStateInfo = state
.getStateInfoById(issuerId);
if (issuerLatestStateInfo.state != issuerClaimNonRevState) {
// Get the time of the latest state and compare it to the transition time of state provided by the user.
StateV2.StateInfo memory issuerClaimNonRevStateInfo = state
.getStateInfoByIdAndState(issuerId, issuerClaimNonRevState);

if (
issuerClaimNonRevLatestStateInfo.id == 0 ||
issuerClaimNonRevLatestStateInfo.id != issuerId
issuerClaimNonRevStateInfo.id == 0 ||
issuerClaimNonRevStateInfo.id != issuerId
) {
revert("state in transition info contains invalid id");
}

if (issuerClaimNonRevLatestStateInfo.replacedAtTimestamp == 0) {
revert("Non-Latest state doesn't contain replacement information");
if (issuerClaimNonRevStateInfo.replacedAtTimestamp == 0) {
revert(
"Non-Latest state doesn't contain replacement information"
);
}

if (
block.timestamp - issuerClaimNonRevLatestStateInfo.replacedAtTimestamp >
block.timestamp -
issuerClaimNonRevStateInfo.replacedAtTimestamp >
revocationStateExpirationTime
) {
revert("Non-Revocation state of Issuer expired");
}

if (block.timestamp - proofGenerationTimestamp > proofGenerationExpirationTime) {
revert("Generated proof is outdated");
}

}
}

if (
block.timestamp - proofGenerationTimestamp >
proofGenerationExpirationTime
) {
revert("Generated proof is outdated");
}
return (true);
}
}
}