diff --git a/contracts/examples/ERC20Verifier.sol b/contracts/examples/ERC20Verifier.sol index 9e68238..627a038 100644 --- a/contracts/examples/ERC20Verifier.sol +++ b/contracts/examples/ERC20Verifier.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity 0.8.16; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@iden3/contracts/lib/GenesisUtils.sol"; -import "@iden3/contracts/interfaces/ICircuitValidator.sol"; -import "@iden3/contracts/verifiers/ZKPVerifier.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {GenesisUtils} from "@iden3/contracts/lib/GenesisUtils.sol"; +import {ICircuitValidator} from "@iden3/contracts/interfaces/ICircuitValidator.sol"; +import {ZKPVerifier} from "@iden3/contracts/verifiers/ZKPVerifier.sol"; contract ERC20Verifier is ERC20, ZKPVerifier { uint64 public constant TRANSFER_REQUEST_ID = 1; diff --git a/contracts/examples/IdentityExample.sol b/contracts/examples/IdentityExample.sol new file mode 100644 index 0000000..5ffe74f --- /dev/null +++ b/contracts/examples/IdentityExample.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.16; + +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {IState} from "@iden3/contracts/interfaces/IState.sol"; +import {ClaimBuilder} from "@iden3/contracts/lib/ClaimBuilder.sol"; +import {OnChainIdentity} from "@iden3/contracts/lib/OnChainIdentity.sol"; +import {IdentityBase} from "@iden3/contracts/lib/IdentityBase.sol"; + +// /** +// * @dev Contract managing onchain identity +// */ +contract IdentityExample is IdentityBase, OwnableUpgradeable { + using OnChainIdentity for OnChainIdentity.Identity; + + // This empty reserved space is put in place to allow future versions + // of the State contract to inherit from other contracts without a risk of + // breaking the storage layout. This is necessary because the parent contracts in the + // future may introduce some storage variables, which are placed before the State + // contract's storage variables. + // (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps) + // slither-disable-next-line shadowing-state + // slither-disable-next-line unused-state + uint256[500] private __gap; + + function initialize(address _stateContractAddr) public override initializer { + super.initialize(_stateContractAddr); + __Ownable_init(); + } + + function addClaimAndTransit(uint256[8] calldata claim) public onlyOwner { + addClaim(claim); + transitState(); + } + + function addClaimHashAndTransit(uint256 hashIndex, uint256 hashValue) public onlyOwner { + addClaimHash(hashIndex, hashValue); + transitState(); + } + + function revokeClaimAndTransit(uint64 revocationNonce) public onlyOwner { + revokeClaim(revocationNonce); + transitState(); + } + + /** + * @dev Add claim + * @param claim - claim data + */ + function addClaim(uint256[8] calldata claim) public virtual onlyOwner { + identity.addClaim(claim); + } + + /** + * @dev Add claim hash + * @param hashIndex - hash of claim index part + * @param hashValue - hash of claim value part + */ + function addClaimHash(uint256 hashIndex, uint256 hashValue) public virtual onlyOwner { + identity.addClaimHash(hashIndex, hashValue); + } + + /** + * @dev Revoke claim using it's revocationNonce + * @param revocationNonce - revocation nonce + */ + function revokeClaim(uint64 revocationNonce) public virtual onlyOwner { + identity.revokeClaim(revocationNonce); + } + + /** + * @dev Make state transition + */ + function transitState() public virtual onlyOwner { + identity.transitState(); + } + + /** + * @dev Calculate IdentityState + * @return IdentityState + */ + function calcIdentityState() public view virtual returns (uint256) { + return identity.calcIdentityState(); + } + + function newClaimData() public pure virtual returns (ClaimBuilder.ClaimData memory) { + ClaimBuilder.ClaimData memory claimData; + return claimData; + } + + /** + * @dev Builds claim + * @param claimData - claim data + * @return binary claim + */ + function buildClaim( + ClaimBuilder.ClaimData calldata claimData + ) public pure virtual returns (uint256[8] memory) { + return ClaimBuilder.build(claimData); + } +} diff --git a/contracts/examples/Imports.sol b/contracts/examples/Imports.sol index 6ed6d59..c9d4fa1 100644 --- a/contracts/examples/Imports.sol +++ b/contracts/examples/Imports.sol @@ -1,5 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.16; -import "@iden3/contracts/lib/Poseidon.sol"; -import "@iden3/contracts/state/StateV2.sol"; -import "@iden3/contracts/lib/verifierV2.sol"; +import{ + PoseidonUnit1L, + PoseidonUnit2L, + PoseidonUnit3L, + PoseidonUnit4L, + PoseidonUnit5L, + PoseidonUnit6L, + SpongePoseidon, + PoseidonFacade} from "@iden3/contracts/lib/Poseidon.sol"; +import {StateV2} from "@iden3/contracts/state/StateV2.sol"; +import {VerifierV2} from "@iden3/contracts/lib/verifierV2.sol"; diff --git a/contracts/validators/CredentialAtomicQueryMTPValidator.sol b/contracts/validators/CredentialAtomicQueryMTPValidator.sol index a0b9149..eacc265 100644 --- a/contracts/validators/CredentialAtomicQueryMTPValidator.sol +++ b/contracts/validators/CredentialAtomicQueryMTPValidator.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.16; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "@iden3/contracts/lib/GenesisUtils.sol"; -import "@iden3/contracts/interfaces/ICircuitValidator.sol"; -import "@iden3/contracts/interfaces/IVerifier.sol"; -import "@iden3/contracts/interfaces/IState.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +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"; contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValidator { string constant CIRCUIT_ID = "credentialAtomicQueryMTPV2OnChain"; @@ -15,12 +15,14 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida IState public state; uint256 public revocationStateExpirationTime; + uint256 public proofGenerationExpirationTime; function initialize( address _verifierContractAddr, address _stateContractAddr ) public initializer { revocationStateExpirationTime = 1 hours; + proofGenerationExpirationTime = 1 hours; verifier = IVerifier(_verifierContractAddr); state = IState(_stateContractAddr); __Ownable_init(); @@ -30,6 +32,10 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida revocationStateExpirationTime = expirationTime; } + function setProofGenerationExpirationTime(uint256 expirationTime) public virtual onlyOwner { + proofGenerationExpirationTime = expirationTime; + } + function getCircuitId() external pure returns (string memory id) { return CIRCUIT_ID; } @@ -55,6 +61,7 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida uint256 issuerId = inputs[6]; uint256 issuerClaimIdenState = inputs[7]; uint256 issuerClaimNonRevState = inputs[9]; + uint256 proofGenerationTimestamp = inputs[10]; IState.GistRootInfo memory rootInfo = state.getGISTRootInfo(gistRoot); @@ -101,9 +108,13 @@ contract CredentialAtomicQueryMTPValidator is OwnableUpgradeable, ICircuitValida ) { revert("Non-Revocation state of Issuer expired"); } + + if (block.timestamp - proofGenerationTimestamp > proofGenerationExpirationTime) { + revert("Generated proof is outdated"); + } } } return (true); } -} +} \ No newline at end of file diff --git a/contracts/validators/CredentialAtomicQuerySigValidator.sol b/contracts/validators/CredentialAtomicQuerySigValidator.sol index 132c40b..7e5d443 100644 --- a/contracts/validators/CredentialAtomicQuerySigValidator.sol +++ b/contracts/validators/CredentialAtomicQuerySigValidator.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.0; +pragma solidity 0.8.16; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "@iden3/contracts/lib/GenesisUtils.sol"; -import "@iden3/contracts/interfaces/ICircuitValidator.sol"; -import "@iden3/contracts/interfaces/IVerifier.sol"; -import "@iden3/contracts/interfaces/IState.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +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"; contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValidator { string constant CIRCUIT_ID = "credentialAtomicQuerySigV2OnChain"; @@ -15,12 +15,14 @@ contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValida IState public state; uint256 public revocationStateExpirationTime; + uint256 public proofGenerationExpirationTime; function initialize( address _verifierContractAddr, address _stateContractAddr ) public initializer { revocationStateExpirationTime = 1 hours; + proofGenerationExpirationTime = 1 hours; verifier = IVerifier(_verifierContractAddr); state = IState(_stateContractAddr); __Ownable_init(); @@ -30,6 +32,10 @@ contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValida revocationStateExpirationTime = expirationTime; } + function setProofGenerationExpirationTime(uint256 expirationTime) public virtual onlyOwner { + proofGenerationExpirationTime = expirationTime; + } + function getCircuitId() external pure returns (string memory id) { return CIRCUIT_ID; } @@ -53,6 +59,7 @@ contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValida uint256 gistRoot = inputs[6]; uint256 issuerId = inputs[7]; uint256 issuerClaimNonRevState = inputs[9]; + uint256 proofGenerationTimestamp = inputs[10]; IState.GistRootInfo memory rootInfo = state.getGISTRootInfo(gistRoot); @@ -99,8 +106,13 @@ contract CredentialAtomicQuerySigValidator is OwnableUpgradeable, ICircuitValida ) { revert("Non-Revocation state of Issuer expired"); } + + if (block.timestamp - proofGenerationTimestamp > proofGenerationExpirationTime) { + revert("Generated proof is outdated"); + } + } } return (true); } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7976b67..67e8752 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "@iden3/contracts": "^1.0.0", + "@iden3/contracts": "^1.1.0", "@openzeppelin/contracts": "^4.6.0", "@openzeppelin/contracts-upgradeable": "^4.8.3", "braces": ">=3.0.2", @@ -1693,9 +1693,9 @@ "integrity": "sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==" }, "node_modules/@iden3/contracts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@iden3/contracts/-/contracts-1.0.0.tgz", - "integrity": "sha512-8RUw6tBWMduNvLDeeQWCDix5OYK4/XrEwk2HV3LVdEi08iSHI6MT5ECixN6eWSu+XmyqNugZE8USoroF2X8BIQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@iden3/contracts/-/contracts-1.1.0.tgz", + "integrity": "sha512-/VDTVOxgsbwrwJCT43aP7X3eWIMWHW0SpOIH6iWTXQlDH5eI0mLOPeeWxUFVkjMia4z48L+KIhsBe9y59uJxlw==", "dependencies": { "@openzeppelin/contracts": "^4.7.3", "@openzeppelin/contracts-upgradeable": "^4.8.2" @@ -28260,9 +28260,9 @@ } }, "@iden3/contracts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@iden3/contracts/-/contracts-1.0.0.tgz", - "integrity": "sha512-8RUw6tBWMduNvLDeeQWCDix5OYK4/XrEwk2HV3LVdEi08iSHI6MT5ECixN6eWSu+XmyqNugZE8USoroF2X8BIQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@iden3/contracts/-/contracts-1.1.0.tgz", + "integrity": "sha512-/VDTVOxgsbwrwJCT43aP7X3eWIMWHW0SpOIH6iWTXQlDH5eI0mLOPeeWxUFVkjMia4z48L+KIhsBe9y59uJxlw==", "requires": { "@openzeppelin/contracts": "^4.7.3", "@openzeppelin/contracts-upgradeable": "^4.8.2" diff --git a/package.json b/package.json index face8e1..2fbfcc9 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "typescript": "^4.6.4" }, "dependencies": { - "@iden3/contracts": "^1.0.0", + "@iden3/contracts": "^1.1.0", "@openzeppelin/contracts": "^4.6.0", "@openzeppelin/contracts-upgradeable": "^4.8.3", "braces": ">=3.0.2", diff --git a/test/helpers/ChainIdDefTypeMap.ts b/test/helpers/ChainIdDefTypeMap.ts new file mode 100644 index 0000000..04aa019 --- /dev/null +++ b/test/helpers/ChainIdDefTypeMap.ts @@ -0,0 +1,5 @@ +export const chainIdDefaultIdTypeMap = new Map() + .set(31337, '0x0212') // hardhat + .set(80001, '0x0212') // polygon mumbai + .set(137, '0x0211'); // polygon main + \ No newline at end of file diff --git a/test/helpers/OnchainIdentityDeployHelper.ts b/test/helpers/OnchainIdentityDeployHelper.ts new file mode 100644 index 0000000..4ae72a0 --- /dev/null +++ b/test/helpers/OnchainIdentityDeployHelper.ts @@ -0,0 +1,103 @@ +import { ethers, upgrades } from "hardhat"; +import { Contract } from "ethers"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; + +export class OnchainIdentityDeployHelper { + constructor( + private signers: SignerWithAddress[], + private readonly enableLogging: boolean = false + ) {} + + static async initialize( + signers: SignerWithAddress[] | null = null, + enableLogging = false + ): Promise { + let sgrs; + if (signers === null) { + sgrs = await ethers.getSigners(); + } else { + sgrs = signers; + } + return new OnchainIdentityDeployHelper(sgrs, enableLogging); + } + + async deployIdentity( + state: Contract, + smtLib: Contract, + poseidon1: Contract, + poseidon2: Contract, + poseidon3: Contract, + poseidon4: Contract + ): Promise<{ + identity: Contract; + }> { + const owner = this.signers[0]; + + this.log("======== Identity: deploy started ========"); + + const cb = await this.deployClaimBuilder(); + const il = await this.deployIdentityLib(smtLib.address, poseidon3.address, poseidon4.address); + + this.log("deploying Identity..."); + const IdentityFactory = await ethers.getContractFactory("IdentityExample", { + libraries: { + ClaimBuilder: cb.address, + OnChainIdentity: il.address, + }, + }); + // const IdentityFactory = await ethers.getContractFactory("Identity"); + const Identity = await upgrades.deployProxy(IdentityFactory, [state.address], { + unsafeAllowLinkedLibraries: true, + }); + await Identity.deployed(); + this.log(`Identity contract deployed to address ${Identity.address} from ${owner.address}`); + + this.log("======== Identity: deploy completed ========"); + + return { + identity: Identity, + }; + } + + async deployClaimBuilder(): Promise { + const ClaimBuilder = await ethers.getContractFactory("ClaimBuilder"); + const cb = await ClaimBuilder.deploy(); + await cb.deployed(); + this.enableLogging && this.log(`ClaimBuilder deployed to: ${cb.address}`); + + return cb; + } + + async deployIdentityLib(smtpAddress: string, poseidonUtil3lAddress: string, poseidonUtil4lAddress: string): Promise { + const Identity = await ethers.getContractFactory("OnChainIdentity", { libraries: { + SmtLib: smtpAddress, + PoseidonUnit3L: poseidonUtil3lAddress, + PoseidonUnit4L: poseidonUtil4lAddress, + }}); + const il = await Identity.deploy(); + await il.deployed(); + this.enableLogging && this.log(`ClaimBuilder deployed to: ${il.address}`); + + return il; + } + + async deployClaimBuilderWrapper(): Promise<{ + address: string; + }> { + + const cb = await this.deployClaimBuilder(); + + const ClaimBuilderWrapper = await ethers.getContractFactory("ClaimBuilderWrapper", { + libraries: { + ClaimBuilder: cb.address + } + }); + const claimBuilderWrapper = await ClaimBuilderWrapper.deploy(); + console.log("ClaimBuilderWrapper deployed to:", claimBuilderWrapper.address); + return claimBuilderWrapper; + } + + private log(...args): void { + this.enableLogging && console.log(args); + } +} diff --git a/test/helpers/StateDeployHelper.ts b/test/helpers/StateDeployHelper.ts index 95c16f8..61f3073 100644 --- a/test/helpers/StateDeployHelper.ts +++ b/test/helpers/StateDeployHelper.ts @@ -1,7 +1,8 @@ -import { ethers, upgrades } from "hardhat"; +import { ethers, upgrades, network } from "hardhat"; import { Contract } from "ethers"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { deployPoseidons } from "../utils/deploy-poseidons.util"; +import { chainIdDefaultIdTypeMap } from "./ChainIdDefTypeMap"; const SMT_MAX_DEPTH = 64; @@ -32,6 +33,7 @@ export class StateDeployHelper { poseidon1: Contract; poseidon2: Contract; poseidon3: Contract; + poseidon4: Contract; }> { this.log("======== StateV2: deploy started ========"); @@ -47,9 +49,9 @@ export class StateDeployHelper { ); this.log("deploying poseidons..."); - const [poseidon1Elements, poseidon2Elements, poseidon3Elements] = await deployPoseidons( + const [poseidon1Elements, poseidon2Elements, poseidon3Elements, poseidon4Elements] = await deployPoseidons( owner, - [1, 2, 3] + [1, 2, 3, 4] ); this.log("deploying SmtLib..."); @@ -66,7 +68,11 @@ export class StateDeployHelper { PoseidonUnit1L: poseidon1Elements.address, }, }); - const stateV2 = await upgrades.deployProxy(StateV2Factory, [verifier.address], { + + const { defaultIdType, chainId } = await this.getDefaultIdType(); + this.log(`found defaultIdType ${defaultIdType} for chainId ${chainId}`); + + const stateV2 = await upgrades.deployProxy(StateV2Factory, [verifier.address, defaultIdType], { unsafeAllowLinkedLibraries: true, }); await stateV2.deployed(); @@ -82,6 +88,7 @@ export class StateDeployHelper { poseidon1: poseidon1Elements, poseidon2: poseidon2Elements, poseidon3: poseidon3Elements, + poseidon4: poseidon4Elements, }; } @@ -140,6 +147,16 @@ export class StateDeployHelper { validator }; } + + async getDefaultIdType(): Promise<{defaultIdType: number, chainId: number}> { + const chainId = parseInt(await network.provider.send('eth_chainId'), 16); + const defaultIdType = chainIdDefaultIdTypeMap.get(chainId); + if (!defaultIdType) { + throw new Error(`Failed to find defaultIdType in Map for chainId ${chainId}`); + } + return { defaultIdType, chainId }; + } + private log(...args): void { this.enableLogging && console.log(args); } diff --git a/test/onchain-identity/index.ts b/test/onchain-identity/index.ts new file mode 100644 index 0000000..ad2965b --- /dev/null +++ b/test/onchain-identity/index.ts @@ -0,0 +1,572 @@ +import { expect } from "chai"; +import { ethers, network } from "hardhat"; +import { OnchainIdentityDeployHelper } from "../helpers/OnchainIdentityDeployHelper"; +import { StateDeployHelper } from "../helpers/StateDeployHelper"; + +describe("Next tests reproduce identity life cycle", function() { + this.timeout(10000); + + let identity; + let latestSavedState; + let latestComputedState; + + before(async function () { + const signer = await ethers.getImpersonatedSigner("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); + await network.provider.send("hardhat_setBalance", [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0x1000000000000000000", + ]); + + await network.provider.send("hardhat_setNonce", [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0xffffffff0000" + ]); + + const stDeployHelper = await StateDeployHelper.initialize([signer]); + const deployHelper = await OnchainIdentityDeployHelper.initialize([signer]); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + describe("create identity", function () { + it("deploy state and identity", async function () { + expect(await identity.getIsOldStateGenesis()).to.be.equal( + true + ); + }); + + it("validate identity's id", async function () { + const id = await identity.getId(); + + console.log(identity.address); + + expect(id).to.be.equal( + 16318200065989903207865860093614592605747279308745685922538039864771744258n + ); + + console.log(BigInt(id).toString(16)); + + }); + }); + + describe("validate initial identity", function () { + let initialClaimTreeRoot, initialRevocationTreeRoot, initialRootOfRootsTreeRoot: any; + before(async function () { + initialClaimTreeRoot = await identity.getClaimsTreeRoot(); + initialRevocationTreeRoot = await identity.getRevocationsTreeRoot(); + initialRootOfRootsTreeRoot = await identity.getRootsTreeRoot(); + }); + + it("trees should be empty", async function () { + expect(initialClaimTreeRoot).be.equal(0); + expect(initialRevocationTreeRoot).to.be.equal(0); + expect(initialRootOfRootsTreeRoot).to.be.equal(0); + }); + + it("last roots should be empty", async function () { + const lastClaimTreeRoot = await identity.getLastClaimsRoot(); + const lastRevocationTreeRoot = await identity.getLastRevocationsRoot(); + const lastRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + + expect(lastClaimTreeRoot).to.be.equal(initialClaimTreeRoot); + expect(lastRevocationTreeRoot).to.be.equal(0); + expect(lastRootOfRootsTreeRoot).to.be.equal(0); + }); + it("since the identity did not perform the transition - the isGenesis flag should be true", async function () { + const isOldStateGenesis = await identity.getIsOldStateGenesis(); + expect(isOldStateGenesis).to.be.true; + }); + it( + "latest identity state should be empty", + async function () { + latestSavedState = await identity.getIdentityLatestState(); + expect(latestSavedState).to.be.equal(0); + } + ); + }); + + describe("add claim", function () { + let initialClaimTreeRoot, + initialRevocationTreeRoot, + initialRootOfRootsTreeRoot, + lastClaimTreeRoot, + lastRevocationTreeRoot, + lastRootOfRootsTreeRoot; + + before(async function () { + initialClaimTreeRoot = await identity.getClaimsTreeRoot(); + initialRevocationTreeRoot = await identity.getRevocationsTreeRoot(); + initialRootOfRootsTreeRoot = await identity.getRootsTreeRoot(); + + lastClaimTreeRoot = await identity.getLastClaimsRoot(); + lastRevocationTreeRoot = await identity.getLastRevocationsRoot(); + lastRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + await identity.addClaimHash(1, 2); + }); + + it("we should have proof about claim existing", async function () { + const proof = await identity.getClaimProof(1); + expect(proof).to.be.not.null; + expect(proof.existence).to.be.true; + }); + + it("after insert identity should update only claims tree root", async function () { + const afterInsertClaimTreeRoot = await identity.getClaimsTreeRoot(); + expect(afterInsertClaimTreeRoot).to.be.not.equal(initialClaimTreeRoot); + }); + + it("another trees should be empty", async function () { + const afterInsertRevocationTreeRoot = await identity.getRevocationsTreeRoot(); + const afterInsertRootOfRootsTreeRoot = await identity.getRootsTreeRoot(); + + expect(afterInsertRevocationTreeRoot).to.be.equal(initialRevocationTreeRoot); + expect(afterInsertRootOfRootsTreeRoot).to.be.equal(initialRootOfRootsTreeRoot); + }); + + it("latest roots should't be change", async function () { + const afterInsertLastClaimTreeRoot = await identity.getLastClaimsRoot(); + const afterInsertLastRevocationTreeRoot = await identity.getLastRevocationsRoot(); + const afterInsertLastRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + expect(afterInsertLastClaimTreeRoot).to.be.equal(lastClaimTreeRoot); + expect(afterInsertLastRevocationTreeRoot).to.be.equal(lastRevocationTreeRoot); + expect(afterInsertLastRootOfRootsTreeRoot).to.be.equal(lastRootOfRootsTreeRoot); + }); + + it("computes state should be different from latest saved state", async function () { + latestComputedState = await identity.calcIdentityState(); + latestSavedState = await identity.getIdentityLatestState(); + expect(latestComputedState).to.be.not.equal(latestSavedState); + }); + }); + + describe("make transition", function () { + let beforeTransitionClaimTreeRoot, + beforeTransitionRevocationTreeRoot, + beforeTransitionRootOfRootsTreeRoot; + + before(async function () { + beforeTransitionClaimTreeRoot = await identity.getLastClaimsRoot(); + beforeTransitionRevocationTreeRoot = await identity.getLastRevocationsRoot(); + beforeTransitionRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + await identity.transitState(); + }); + + it("latest roots for ClaimsTree and RootOfRoots should be updated", async function () { + const afterTransitionClaimTreeRoot = await identity.getLastClaimsRoot(); + expect(afterTransitionClaimTreeRoot).to.be.not.equal(beforeTransitionClaimTreeRoot); + }); + it("Revocation root should be empty", async function () { + const afterTransitionRevocationTreeRoot = await identity.getLastRevocationsRoot(); + expect(afterTransitionRevocationTreeRoot).to.be.equal(0); + expect(afterTransitionRevocationTreeRoot).to.be.equal(beforeTransitionRevocationTreeRoot); + }); + + it("Root of roots and claims root should be updated", async function () { + const afterTranstionLatestSavedState = await identity.getIdentityLatestState(); + const afterTransitionRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + + expect(afterTransitionRootOfRootsTreeRoot).to.be.not.equal(0); + expect(afterTransitionRootOfRootsTreeRoot).to.be.not.equal( + beforeTransitionRootOfRootsTreeRoot + ); + expect(latestSavedState).to.be.not.equal(afterTranstionLatestSavedState); + latestSavedState = afterTranstionLatestSavedState; + }); + it("calculatet and saved status should be same", async function () { + latestComputedState = await identity.calcIdentityState(); + expect(latestComputedState).to.be.equal(latestSavedState); + }); + }); + + describe("revoke state", function () { + let beforeRevocationClaimTreeRoot, + beforeRevocationRevocationTreeRoot, + beforeRevocationRootOfRootsTreeRoot; + + before(async function () { + beforeRevocationClaimTreeRoot = await identity.getLastClaimsRoot(); + beforeRevocationRevocationTreeRoot = await identity.getLastRevocationsRoot(); + beforeRevocationRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + await identity.revokeClaim(1); + }); + + it("revoced index should exists in Revocation tree", async function () { + const proof = await identity.getRevocationProof(1); + expect(proof).to.be.not.null; + expect(proof.existence).to.be.true; + }); + + it("transit of revocation tree shouldn't update root of roots tree", async function () { + const beforeRevocationRootOfRootsTreeRoot = await identity.getLastRevocationsRoot(); + expect(beforeRevocationRootOfRootsTreeRoot).to.be.equal(beforeRevocationRevocationTreeRoot); + }); + + it("Root of Roots and Claims Root should be changed", async function () { + const afterRevocationClaimTreeRoot = await identity.getLastClaimsRoot(); + const afterRevocationRootOfRootsTreeRoot = await identity.getLastRootsRoot(); + + expect(afterRevocationClaimTreeRoot).to.be.equal(beforeRevocationClaimTreeRoot); + expect(afterRevocationRootOfRootsTreeRoot).to.be.equal(beforeRevocationRootOfRootsTreeRoot); + }); + }); + + describe("make transition after revocation", function () { + let beforeTransitionLatestSavedState; + before(async function () { + beforeTransitionLatestSavedState = await identity.getIdentityLatestState(); + await identity.transitState(); + }); + it("state should be updated", async function () { + const afterTransitionLatestSavedState = await identity.getIdentityLatestState(); + expect(beforeTransitionLatestSavedState).to.be.not.equal(afterTransitionLatestSavedState); + }); + }); +}); + +describe("Claims tree proofs", () => { + let identity; + let targetRoot; + + before(async function () { + const stDeployHelper = await StateDeployHelper.initialize(); + const deployHelper = await OnchainIdentityDeployHelper.initialize(); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + it("Insert new claim and generate proof", async function () { + await identity.addClaimHash(1, 2); + const proof = await identity.getClaimProof(1); + targetRoot = await identity.getClaimsTreeRoot(); + expect(proof.root).to.be.equal(targetRoot); + expect(proof.existence).to.be.true; + expect(proof.index).to.be.equal(1); + expect(proof.value).to.be.equal(2); + expect(proof.auxExistence).to.be.false; + expect(proof.auxIndex).to.be.equal(0); + expect(proof.auxValue).to.be.equal(0); + }); + + it("Get proof for claim by root", async function () { + await identity.addClaimHash(2, 2); + + // using not latest Root + let proof = await identity.getClaimProofByRoot(2, targetRoot); + expect(proof.root).to.be.equal(targetRoot); + expect(proof.existence).to.be.false; + + // update latest root + targetRoot = await identity.getClaimsTreeRoot(); + proof = await identity.getClaimProofByRoot(2, targetRoot); + expect(proof.root).to.be.equal(targetRoot); + expect(proof.existence).to.be.true; + expect(proof.index).to.be.equal(2); + expect(proof.value).to.be.equal(2); + expect(proof.auxExistence).to.be.false; + expect(proof.auxIndex).to.be.equal(0); + expect(proof.auxValue).to.be.equal(0); + }); +}); + +describe("Revocation tree proofs", () => { + let identity; + let targetRoot; + + before(async function () { + const stDeployHelper = await StateDeployHelper.initialize(); + const deployHelper = await OnchainIdentityDeployHelper.initialize(); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + it("Insert new record to revocation tree and generate proof", async function () { + await identity.revokeClaim(1); + const proof = await identity.getRevocationProof(1); + targetRoot = await identity.getRevocationsTreeRoot(); + expect(proof.root).to.be.equal(targetRoot); + expect(proof.existence).to.be.true; + expect(proof.index).to.be.equal(1); + expect(proof.value).to.be.equal(0); + expect(proof.auxExistence).to.be.false; + expect(proof.auxIndex).to.be.equal(0); + expect(proof.auxValue).to.be.equal(0); + }); + + it("Get proof for revocation by root", async function () { + await identity.revokeClaim(2); + + // using not latest revocation root + let proof = await identity.getRevocationProofByRoot(2, targetRoot); + expect(proof.root).to.be.equal(targetRoot); + expect(proof.existence).to.be.false; + + // update latest root + targetRoot = await identity.getRevocationsTreeRoot(); + proof = await identity.getRevocationProofByRoot(2, targetRoot); + expect(proof.root).to.be.equal(targetRoot); + expect(proof.existence).to.be.true; + expect(proof.index).to.be.equal(2); + expect(proof.value).to.be.equal(0); + expect(proof.auxExistence).to.be.false; + expect(proof.auxIndex).to.be.equal(0); + expect(proof.auxValue).to.be.equal(0); + }); +}); + +describe("Root of roots tree proofs", () => { + let identity; + let latestRootOfRoots; + + before(async function () { + const stDeployHelper = await StateDeployHelper.initialize(); + const deployHelper = await OnchainIdentityDeployHelper.initialize(); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + describe("Insert two claims and make transtion state", () => { + before(async function () { + await identity.addClaimHash(1, 2); + await identity.addClaimHash(2, 2); + await identity.transitState(); + }); + it("Check that root of roots not empty", async function () { + latestRootOfRoots = await identity.getRootsTreeRoot(); + expect(latestRootOfRoots).to.be.not.equal(0); + }); + }); + + describe("Get current Claims tree root and check that is root exists on Root of Roots tree", () => { + let currentClaimsTreeRoot; + before(async function () { + currentClaimsTreeRoot = await identity.getClaimsTreeRoot(); + await identity.addClaimHash(3, 2); + await identity.transitState(); + }); + + it("Check that Root of Roots tree contains old Claims tee root", async function () { + const proof = await identity.getRootProof(currentClaimsTreeRoot); + expect(proof.existence).to.be.true; + }); + }); + + describe("Check historical Claim tree root in claims tree root", () => { + let currentClaimsTreeRoot, latestRootOfRootsRoot; + before(async function () { + latestRootOfRootsRoot = await identity.getLastRootsRoot(); + await identity.addClaimHash(4, 2); + await identity.transitState(); + currentClaimsTreeRoot = await identity.getClaimsTreeRoot(); + }); + + it("Check that Root of Roots tree not contains latest claims tree root", async function () { + const proof = await identity.getRootProofByRoot(currentClaimsTreeRoot, latestRootOfRootsRoot); + expect(proof.root).to.be.equal(latestRootOfRootsRoot); + expect(proof.existence).to.be.false; + }); + + it("Check that current Root of roots contains latest claims tree root", async function () { + const proof = await identity.getRootProof(currentClaimsTreeRoot); + expect(proof.existence).to.be.true; + }); + }); +}); + +describe("Compare historical roots with latest roots from tree", () => { + let identity; + let latestState; + + before(async function () { + const stDeployHelper = await StateDeployHelper.initialize(); + const deployHelper = await OnchainIdentityDeployHelper.initialize(); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + describe("Insert and revoke claims", () => { + before(async function () { + await identity.addClaimHash(1, 2); + await identity.addClaimHash(2, 2); + await identity.revokeClaim(1); + await identity.transitState(); + + latestState = await identity.getIdentityLatestState(); + }); + it("Compare latest claims tree root", async function () { + const latestClaimsTreeRoot = await identity.getClaimsTreeRoot(); + const history = await identity.getRootsByState(latestState); + + expect(latestClaimsTreeRoot).to.be.not.equal(0); + expect(history.claimsRoot).to.be.deep.equal(latestClaimsTreeRoot); + }); + it("Compare latest revocations tree root", async function () { + const latestReocationsTreeRoot = await identity.getRevocationsTreeRoot(); + const history = await identity.getRootsByState(latestState); + + expect(latestReocationsTreeRoot).to.be.not.equal(0); + expect(history.revocationsRoot).to.be.deep.equal(latestReocationsTreeRoot); + }); + it("Compare latest roots tree root", async function () { + const latestRootOfRoots = await identity.getRootsTreeRoot(); + const history = await identity.getRootsByState(latestState); + + expect(latestRootOfRoots).to.be.not.equal(0); + expect(history.rootsRoot).to.be.deep.equal(latestRootOfRoots); + }); + }); +}); + +describe("Compare historical roots with latest roots from tree", () => { + let identity, prevState; + let historyClaimsTreeRoot, historyRevocationsTreeRoot, historyRootsTreeRoot; + + before(async function () { + const stDeployHelper = await StateDeployHelper.initialize(); + const deployHelper = await OnchainIdentityDeployHelper.initialize(); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + describe("Check prev states", () => { + before(async function () { + await identity.addClaimHash(1, 2); + await identity.revokeClaim(1); + await identity.transitState(); + prevState = await identity.getIdentityLatestState(); + }); + it("Compare latest claims tree root", async function () { + const latestClaimsTreeRoot = await identity.getClaimsTreeRoot(); + const history = await identity.getRootsByState(prevState); + + expect(latestClaimsTreeRoot).to.be.not.equal(0); + expect(history.claimsRoot).to.be.deep.equal(latestClaimsTreeRoot); + historyClaimsTreeRoot = latestClaimsTreeRoot; + }); + it("Compare latest revocations tree root", async function () { + const latestReocationsTreeRoot = await identity.getRevocationsTreeRoot(); + const history = await identity.getRootsByState(prevState); + + expect(latestReocationsTreeRoot).to.be.not.equal(0); + expect(history.revocationsRoot).to.be.deep.equal(latestReocationsTreeRoot); + historyRevocationsTreeRoot = latestReocationsTreeRoot; + }); + it("Compare latest roots tree root", async function () { + const latestRootOfRoots = await identity.getRootsTreeRoot(); + const history = await identity.getRootsByState(prevState); + + expect(latestRootOfRoots).to.be.not.equal(0); + expect(history.rootsRoot).to.be.deep.equal(latestRootOfRoots); + historyRootsTreeRoot = latestRootOfRoots; + }); + }); + + describe("Check next states", () => { + before(async function () { + await identity.addClaimHash(2, 2); + await identity.revokeClaim(2); + await identity.transitState(); + }); + it("Check historical claims tree root", async function () { + const latestClaimsTreeRoot = await identity.getClaimsTreeRoot(); + const history = await identity.getRootsByState(prevState); + expect(latestClaimsTreeRoot).to.be.not.equal(0); + expect(history.claimsRoot).to.not.deep.equal(latestClaimsTreeRoot); + expect(history.claimsRoot).to.be.deep.equal(historyClaimsTreeRoot); + }); + it("Check historical revocations tree root", async function () { + const latestReocationsTreeRoot = await identity.getRevocationsTreeRoot(); + const history = await identity.getRootsByState(prevState); + + expect(latestReocationsTreeRoot).to.be.not.equal(0); + expect(history.revocationsRoot).to.not.deep.equal(latestReocationsTreeRoot); + expect(history.revocationsRoot).to.be.deep.equal(historyRevocationsTreeRoot); + }); + it("Check historical roots tree root", async function () { + const latestRootOfRoots = await identity.getRootsTreeRoot(); + const history = await identity.getRootsByState(prevState); + + expect(latestRootOfRoots).to.be.not.equal(0); + expect(history.rootsRoot).to.not.deep.equal(latestRootOfRoots); + expect(history.rootsRoot).to.be.deep.equal(historyRootsTreeRoot); + }); + }); +}); + +describe("Genesis state doens't have history of states", () => { + let identity; + + before(async function () { + const stDeployHelper = await StateDeployHelper.initialize(); + const deployHelper = await OnchainIdentityDeployHelper.initialize(); + const stContracts = await stDeployHelper.deployStateV2(); + const contracts = await deployHelper.deployIdentity( + stContracts.state, + stContracts.smtLib, + stContracts.poseidon1, + stContracts.poseidon2, + stContracts.poseidon3, + stContracts.poseidon4 + ); + identity = contracts.identity; + }); + + describe("Empty history map", () => { + it("Got an error", async function () { + const latestState = await identity.calcIdentityState(); + try { + await identity.getRootsByState(latestState); + expect.fail('The transaction should have thrown an error'); + } catch (err: any) { + expect(err.reason).to.be.equal("Roots for this state doesn't exist"); + } + }); + }); +}); diff --git a/test/validators/mtp/index.ts b/test/validators/mtp/index.ts index c1ce780..43afb2c 100644 --- a/test/validators/mtp/index.ts +++ b/test/validators/mtp/index.ts @@ -7,17 +7,20 @@ import { publishState, } from "../../utils/deploy-utils"; +const tenYears = 315360000; const testCases: any[] = [ { name: "Validate Genesis User State. Issuer Claim IdenState is in Chain. Revocation State is in Chain", stateTransitions: [require("../common-data/issuer_genesis_state.json")], proofJson: require("./data/valid_mtp_user_genesis.json"), + setProofExpiration: tenYears, }, { name: "Validation of proof failed", stateTransitions: [require("../common-data/issuer_genesis_state.json")], proofJson: require("./data/invalid_mtp_user_genesis.json"), - errorMessage: "MTP Proof could not be verified", + errorMessage: "", + setProofExpiration: tenYears, }, { name: "User state is not genesis but latest", @@ -26,7 +29,7 @@ const testCases: any[] = [ require("../common-data/user_state_transition.json"), ], proofJson: require("./data/valid_mtp_user_non_genesis.json"), - errorMessage: "", + setProofExpiration: tenYears, }, { name: "The non-revocation issuer state is not expired (is not too old)", @@ -36,7 +39,7 @@ const testCases: any[] = [ require("../common-data/issuer_next_state_transition.json"), ], proofJson: require("./data/valid_mtp_user_non_genesis.json"), - errorMessage: "", + setProofExpiration: tenYears, }, { name: "The non-revocation issuer state is expired (old enough)", @@ -48,6 +51,17 @@ const testCases: any[] = [ proofJson: require("./data/valid_mtp_user_non_genesis.json"), setExpiration: 1, errorMessage: "Non-Revocation state of Issuer expired", + setProofExpiration: tenYears, + }, + { + name: "The generated proof is expired (old enough)", + stateTransitions: [ + require("../common-data/issuer_genesis_state.json"), + require("../common-data/user_state_transition.json"), + require("../common-data/issuer_next_state_transition.json"), + ], + proofJson: require("./data/valid_mtp_user_non_genesis.json"), + errorMessage: "Generated proof is outdated", }, ]; @@ -86,14 +100,18 @@ describe("Atomic MTP Validator", function () { }; const { inputs, pi_a, pi_b, pi_c } = prepareInputs(test.proofJson); + if (test.setProofExpiration) { + await mtpValidator.setProofGenerationExpirationTime(test.setProofExpiration); + } + if (test.setExpiration) { + await mtpValidator.setRevocationStateExpirationTime(test.setExpiration); + } if (test.errorMessage) { - if (test.setExpiration) { - await mtpValidator.setRevocationStateExpirationTime(test.setExpiration); - } - - ( - expect(mtpValidator.verify(inputs, pi_a, pi_b, pi_c, query.queryHash)).to.be as any - ).revertedWith(test.errorMessage); + await expect(mtpValidator.verify(inputs, pi_a, pi_b, pi_c, query.queryHash)).to.be.revertedWith( + test.errorMessage + ); + } else if (test.errorMessage === "") { + await expect(mtpValidator.verify(inputs, pi_a, pi_b, pi_c, query.queryHash)).to.be.reverted; } else { const verified = await mtpValidator.verify(inputs, pi_a, pi_b, pi_c, query.queryHash); expect(verified).to.be.true; @@ -152,7 +170,6 @@ describe("Atomic MTP Validator", function () { expect((await token.getSupportedRequests()).length).to.be.equal(1); // submit response for non-existing request - await expect(token.submitZKPResponse(2, inputs, pi_a, pi_b, pi_c)).to.be.revertedWith( "validator is not set for this request id" ); @@ -175,6 +192,7 @@ describe("Atomic MTP Validator", function () { } it("Example ERC20 Verifier: set zkp request", async () => { + await mtpValidator.setProofGenerationExpirationTime(tenYears); await erc20VerifierFlow(async (query, token, requestId) => { await token.setZKPRequest( requestId, @@ -188,6 +206,7 @@ describe("Atomic MTP Validator", function () { }); it("Example ERC20 Verifier: set zkp request raw", async () => { + await mtpValidator.setProofGenerationExpirationTime(tenYears); await erc20VerifierFlow(async (query, token, requestId) => { await token.setZKPRequestRaw( requestId, diff --git a/test/validators/sig/index.ts b/test/validators/sig/index.ts index f71978e..61fc4d1 100644 --- a/test/validators/sig/index.ts +++ b/test/validators/sig/index.ts @@ -6,22 +6,21 @@ import { prepareInputs, publishState, } from "../../utils/deploy-utils"; -import { - StateDeployHelper -} from "../../helpers/StateDeployHelper"; - +const tenYears = 315360000; const testCases: any[] = [ { name: "Validate Genesis User State. Issuer Claim IdenState is in Chain. Revocation State is in Chain", stateTransitions: [require("../common-data/issuer_genesis_state.json")], proofJson: require("./data/valid_sig_user_genesis.json"), + setProofExpiration: tenYears, }, { name: "Validation of proof failed", stateTransitions: [require("../common-data/issuer_genesis_state.json")], proofJson: require("./data/invalid_sig_user_genesis.json"), - errorMessage: "MTP Proof could not be verified", + errorMessage: "", + setProofExpiration: tenYears, }, { name: "User state is not genesis but latest", @@ -30,7 +29,7 @@ const testCases: any[] = [ require("../common-data/user_state_transition.json"), ], proofJson: require("./data/valid_sig_user_non_genesis.json"), - errorMessage: "", + setProofExpiration: tenYears, }, { name: "The non-revocation issuer state is not expired (is not too old)", @@ -40,7 +39,7 @@ const testCases: any[] = [ require("../common-data/issuer_next_state_transition.json"), ], proofJson: require("./data/valid_sig_user_non_genesis.json"), - errorMessage: "", + setProofExpiration: tenYears, }, { name: "The non-revocation issuer state is expired (old enough)", @@ -52,6 +51,17 @@ const testCases: any[] = [ proofJson: require("./data/valid_sig_user_non_genesis.json"), setExpiration: 1, errorMessage: "Non-Revocation state of Issuer expired", + setProofExpiration: tenYears, + }, + { + name: "The generated proof is expired (old enough)", + stateTransitions: [ + require("../common-data/issuer_genesis_state.json"), + require("../common-data/user_state_transition.json"), + require("../common-data/issuer_next_state_transition.json"), + ], + proofJson: require("./data/valid_sig_user_non_genesis.json"), + errorMessage: "Generated proof is outdated", }, ]; @@ -90,14 +100,19 @@ describe("Atomic Sig Validator", function () { }; const { inputs, pi_a, pi_b, pi_c } = prepareInputs(test.proofJson); - if (test.errorMessage) { - if (test.setExpiration) { + + if (test.setProofExpiration) { + await sig.setProofGenerationExpirationTime(test.setProofExpiration); + } + if (test.setExpiration) { await sig.setRevocationStateExpirationTime(test.setExpiration); } - - (expect(sig.verify(inputs, pi_a, pi_b, pi_c, query.queryHash)).to.be as any).revertedWith( + if (test.errorMessage) { + await expect(sig.verify(inputs, pi_a, pi_b, pi_c, query.queryHash)).to.be.revertedWith( test.errorMessage ); + } else if (test.errorMessage === "") { + await expect(sig.verify(inputs, pi_a, pi_b, pi_c, query.queryHash)).to.be.reverted; } else { const verified = await sig.verify(inputs, pi_a, pi_b, pi_c, query.queryHash); expect(verified).to.be.true; @@ -162,8 +177,7 @@ describe("Atomic Sig Validator", function () { await expect(token.submitZKPResponse(2, inputs, pi_a, pi_b, pi_c)).to.be.revertedWith( "validator is not set for this request id" ); - - const stateDeployHelper = await StateDeployHelper.initialize(); + // const stateDeployHelper = await StateDeployHelper.initialize(); // const validatorAddress = await token.requestQueries(requestId)).validator // console.log("validator":validatorAddress) @@ -171,7 +185,6 @@ describe("Atomic Sig Validator", function () { // const addr = await stateDeployHelper.upgradeValidator(sig.address,"UPD") // console.log("contract address after:", addr.validator.address) await token.submitZKPResponse(requestId, inputs, pi_a, pi_b, pi_c); - expect(await token.proofs(account, requestId)).to.be.true; // check proof is assigned // check that tokens were minted @@ -188,6 +201,7 @@ describe("Atomic Sig Validator", function () { } it("Example ERC20 Verifier: set zkp request", async () => { + await sig.setProofGenerationExpirationTime(tenYears); await erc20VerifierFlow(async (query, token, requestId) => { await token.setZKPRequest( requestId, @@ -201,6 +215,7 @@ describe("Atomic Sig Validator", function () { }); it("Example ERC20 Verifier: set zkp request raw", async () => { + await sig.setProofGenerationExpirationTime(tenYears); await erc20VerifierFlow(async (query, token, requestId) => { await token.setZKPRequestRaw( requestId,