Skip to content

Commit

Permalink
Merge pull request #1 from rarimo/feature/update_lightweight_state
Browse files Browse the repository at this point in the history
Update LightweightStateV2 contract
  • Loading branch information
Hrom131 authored Jan 27, 2024
2 parents 37a253c + 0dcf6a8 commit f03d059
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 250 deletions.
142 changes: 73 additions & 69 deletions contracts/LightweightStateV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,39 @@ contract LightweightStateV2 is ILightweightStateV2, UUPSSignableUpgradeable, Sig
sourceStateContract = newSourceStateContract_;
}

function signedTransitState(
uint256 prevState_,
function signedTransitGISTData(
uint256 prevGist_,
StateData calldata stateData_,
GistRootData calldata gistData_,
bytes calldata proof_
) external override {
_checkMerkleSignature(_getSignHash(stateData_, gistData_, prevState_, prevGist_), proof_);
_checkMerkleSignature(_getGISTSignHash(gistData_, prevGist_), proof_);

require(
_gistsRootData[gistData_.root].createdAtTimestamp == 0,
"LightweightStateV2: unable to update already stored gist data"
);

if (gistData_.createdAtTimestamp > _gistsRootData[_currentGistRoot].createdAtTimestamp) {
_currentGistRoot = gistData_.root;
}

GistRootData storage _newGistRootData = _gistsRootData[gistData_.root];

_newGistRootData.root = gistData_.root;
_newGistRootData.createdAtTimestamp = gistData_.createdAtTimestamp;
_newGistRootData.createdAtBlock = gistData_.createdAtBlock;

_gistsRootData[prevGist_].replacedByRoot = gistData_.root;

emit SignGISTDataTransited(gistData_.root, prevGist_);
}

function signedTransitStateData(
uint256 prevState_,
StateData calldata stateData_,
bytes calldata proof_
) external override {
_checkMerkleSignature(_getStateSignHash(stateData_, prevState_), proof_);

IdentityInfo storage _identityInfo = _identitiesInfo[stateData_.id];

Expand All @@ -72,32 +97,16 @@ contract LightweightStateV2 is ILightweightStateV2, UUPSSignableUpgradeable, Sig
_identityInfo.lastState = stateData_.state;
}

_identityInfo.statesData[stateData_.state] = stateData_;
_identityInfo.statesData[prevState_].replacedByState = stateData_.state;

if (_currentGistRoot != gistData_.root) {
require(
_gistsRootData[gistData_.root].createdAtTimestamp == 0,
"LightweightStateV2: unable to update already stored gist data"
);
StateData storage _newStateData = _identityInfo.statesData[stateData_.state];

if (
gistData_.createdAtTimestamp > _gistsRootData[_currentGistRoot].createdAtTimestamp
) {
_currentGistRoot = gistData_.root;
}
_newStateData.id = stateData_.id;
_newStateData.state = stateData_.state;
_newStateData.createdAtTimestamp = stateData_.createdAtTimestamp;
_newStateData.createdAtBlock = stateData_.createdAtBlock;

_gistsRootData[gistData_.root] = gistData_;
_gistsRootData[prevGist_].replacedByRoot = gistData_.root;
}
_identityInfo.statesData[prevState_].replacedByState = stateData_.state;

emit SignedStateTransited(
gistData_.root,
stateData_.id,
stateData_.state,
prevState_,
prevGist_
);
emit SignStateDataTransited(stateData_.id, stateData_.state, prevState_);
}

function getStateInfoById(
Expand Down Expand Up @@ -162,18 +171,17 @@ contract LightweightStateV2 is ILightweightStateV2, UUPSSignableUpgradeable, Sig
function _getStateInfo(
uint256 identityId_,
uint256 state_
) internal view returns (StateInfo memory) {
) internal view returns (StateInfo memory stateInfo_) {
IdentityInfo storage _identityInfo = _identitiesInfo[identityId_];

bool isLastState_ = _identityInfo.lastState == state_;

StateData memory stateData_ = _identityInfo.statesData[state_];
StateData storage _replacedStateData = _identityInfo.statesData[
stateData_.replacedByState
];

return
StateInfo({
if (stateData_.id != 0) {
StateData storage _replacedStateData = _identityInfo.statesData[
stateData_.replacedByState
];
bool isLastState_ = _identityInfo.lastState == state_;

stateInfo_ = StateInfo({
id: stateData_.id,
state: stateData_.state,
replacedByState: stateData_.replacedByState,
Expand All @@ -182,63 +190,59 @@ contract LightweightStateV2 is ILightweightStateV2, UUPSSignableUpgradeable, Sig
createdAtBlock: stateData_.createdAtBlock,
replacedAtBlock: isLastState_ ? 0 : _replacedStateData.createdAtBlock
});
}
}

function _getGISTRootInfo(uint256 root_) internal view returns (GistRootInfo memory) {
bool isCurrentRoot_ = root_ == _currentGistRoot;

function _getGISTRootInfo(
uint256 root_
) internal view returns (GistRootInfo memory gistRootInfo_) {
GistRootData memory rootData_ = _gistsRootData[root_];
GistRootData storage _replacedRootData = _gistsRootData[rootData_.replacedByRoot];

return
GistRootInfo({
if (rootData_.root != 0) {
GistRootData storage _replacedRootData = _gistsRootData[rootData_.replacedByRoot];
bool isCurrentRoot_ = root_ == _currentGistRoot;

gistRootInfo_ = GistRootInfo({
root: rootData_.root,
replacedByRoot: rootData_.replacedByRoot,
createdAtTimestamp: rootData_.createdAtTimestamp,
replacedAtTimestamp: isCurrentRoot_ ? 0 : _replacedRootData.createdAtTimestamp,
createdAtBlock: rootData_.createdAtBlock,
replacedAtBlock: isCurrentRoot_ ? 0 : _replacedRootData.createdAtBlock
});
}
}

function _getSignHash(
function _getStateSignHash(
StateData calldata stateData_,
GistRootData calldata gistData_,
uint256 prevState_,
uint256 prevGist_
uint256 prevState_
) internal view returns (bytes32) {
return
keccak256(
abi.encodePacked(
sourceStateContract,
_encodeStateData(stateData_),
_encodeGistData(gistData_),
prevState_,
prevGist_
stateData_.id,
stateData_.state,
stateData_.createdAtTimestamp,
stateData_.createdAtBlock,
prevState_
)
);
}

function _encodeStateData(StateData calldata stateData_) internal pure returns (bytes memory) {
return
abi.encodePacked(
stateData_.id,
stateData_.state,
stateData_.replacedByState,
stateData_.createdAtTimestamp,
stateData_.createdAtBlock
);
}

function _encodeGistData(
GistRootData calldata gistData_
) internal pure returns (bytes memory) {
function _getGISTSignHash(
GistRootData calldata gistData_,
uint256 prevGist_
) internal view returns (bytes32) {
return
abi.encodePacked(
gistData_.root,
gistData_.replacedByRoot,
gistData_.createdAtTimestamp,
gistData_.createdAtBlock
keccak256(
abi.encodePacked(
sourceStateContract,
gistData_.root,
gistData_.createdAtTimestamp,
gistData_.createdAtBlock,
prevGist_
)
);
}
}
33 changes: 22 additions & 11 deletions contracts/interfaces/ILightweightStateV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,23 @@ interface ILightweightStateV2 is IState {

/**
* @notice Event that emitted during the transition of a signed state
* @param newGistRoot the new GIST root
* @param identityId the identifier of the identity for which the state was transited
* @param newIdentityState the new identity state
* @param prevIdentityState the previous identity state
* @param prevGistRoot the previous GIST root
*/
event SignedStateTransited(
uint256 newGistRoot,
event SignStateDataTransited(
uint256 identityId,
uint256 newIdentityState,
uint256 prevIdentityState,
uint256 prevGistRoot
uint256 prevIdentityState
);

/**
* @notice Event that emitted during the transition of a GIST data
* @param newGistRoot the new GIST root
* @param prevGistRoot the previous GIST root
*/
event SignGISTDataTransited(uint256 newGistRoot, uint256 prevGistRoot);

/**
* @notice Function for changing source state contract with signature from Rarimo validators
* @param newSourceStateContract_ the new address for the source state contract
Expand All @@ -94,19 +97,27 @@ interface ILightweightStateV2 is IState {
*/
function changeSigner(bytes calldata newSignerPubKey_, bytes calldata signature_) external;

/**
* @notice Function for transiting information about a specific GIST from the Polygon network
* @param prevGist_ the previous GIST root from the one whose information is passed on
* @param gistData_ the information about the GIST to be saved
* @param proof_ the proof of entry of the relevant leaf into Merkle Tree together with signature from Rarimo validators
*/
function signedTransitGISTData(
uint256 prevGist_,
GistRootData calldata gistData_,
bytes calldata proof_
) external;

/**
* @notice Function for transiting information about a specific identity's state from the Polygon network
* @param prevState_ the previous identity state from the one whose information is passed on
* @param prevGist_ the previous GIST root from the one whose information is passed on
* @param stateData_ the information about the state to be saved
* @param gistData_ the information about the GSIT to be saved
* @param proof_ the proof of entry of the relevant leaf into Merkle Tree together with signature from Rarimo validators
*/
function signedTransitState(
function signedTransitStateData(
uint256 prevState_,
uint256 prevGist_,
StateData calldata stateData_,
GistRootData calldata gistData_,
bytes calldata proof_
) external;

Expand Down
8 changes: 8 additions & 0 deletions contracts/mock/LightweightStateV2Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ pragma solidity 0.8.16;
import "../LightweightStateV2.sol";

contract LightweightStateV2Mock is LightweightStateV2 {
function setSigner(address newSigner_) external {
signer = newSigner_;
}

function convertPubKeyToAddress(bytes calldata pubKey_) external pure returns (address) {
return _convertPubKeyToAddress(pubKey_);
}

function getGISTData(uint256 gistRoot_) external view returns (GistRootData memory) {
return _gistsRootData[gistRoot_];
}
}
3 changes: 3 additions & 0 deletions contracts/mock/tokens/ERC20Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

import "@iden3/contracts/validators/CredentialAtomicQuerySigValidator.sol";
import "@iden3/contracts/validators/CredentialAtomicQueryMTPValidator.sol";

import "@iden3/contracts/lib/verifierSigWrapper.sol";
import "@iden3/contracts/lib/verifierMTPWrapper.sol";

contract ERC20Mock is ERC20 {
uint8 internal _decimals;
Expand Down
18 changes: 9 additions & 9 deletions deploy/3_query_validator_deploy.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Deployer, Logger } from "@solarity/hardhat-migrate";
import { artifacts } from "hardhat";
import { Config, parseConfig, isZeroAddr } from "@/deploy/helpers/config_parser";
import { deployMTPValidatorOffChain, deploySigValidatorOffChain } from "@/deploy/helpers/deploy_helper";
import { deployMTPValidatorOnChain, deploySigValidatorOnChain } from "@/deploy/helpers/deploy_helper";

const PoseidonFacade = artifacts.require("PoseidonFacade");
const LightweightStateV2 = artifacts.require("LightweightStateV2");

const QueryMTPValidatorOffChain = artifacts.require("QueryMTPValidatorOffChain");
const QuerySigValidatorOffChain = artifacts.require("QuerySigValidatorOffChain");
const CredentialAtomicQuerySigValidator = artifacts.require("CredentialAtomicQuerySigValidator");
const CredentialAtomicQueryMTPValidator = artifacts.require("CredentialAtomicQueryMTPValidator");

export = async (deployer: Deployer, logger: Logger) => {
const config: Config = parseConfig();
Expand All @@ -19,21 +19,21 @@ export = async (deployer: Deployer, logger: Logger) => {
const stateAddr = (await LightweightStateV2.deployed()).address;

if (config.validatorContractInfo.isSigValidator) {
queryValidatorAddr = await deploySigValidatorOffChain(deployer, logger, poseidonFacade, stateAddr);
queryValidatorAddr = await deploySigValidatorOnChain(deployer, logger, stateAddr);
} else {
queryValidatorAddr = await deployMTPValidatorOffChain(deployer, logger, poseidonFacade, stateAddr);
queryValidatorAddr = await deployMTPValidatorOnChain(deployer, logger, stateAddr);
}
} else {
queryValidatorAddr = config.validatorContractInfo.validatorAddr;
}

if (config.validatorContractInfo.isSigValidator) {
const querySigValidator = await QuerySigValidatorOffChain.at(queryValidatorAddr);
const querySigValidator = await CredentialAtomicQuerySigValidator.at(queryValidatorAddr);

await QuerySigValidatorOffChain.setAsDeployed(querySigValidator);
await CredentialAtomicQuerySigValidator.setAsDeployed(querySigValidator);
} else {
const queryMTPValidator = await QueryMTPValidatorOffChain.at(queryValidatorAddr);
const queryMTPValidator = await CredentialAtomicQueryMTPValidator.at(queryValidatorAddr);

await QueryMTPValidatorOffChain.setAsDeployed(queryMTPValidator);
await CredentialAtomicQueryMTPValidator.setAsDeployed(queryMTPValidator);
}
};
8 changes: 4 additions & 4 deletions deploy/4_contracts_deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const PoseidonFacade = artifacts.require("PoseidonFacade");
const LightweightStateV2 = artifacts.require("LightweightStateV2");
const ERC1967Proxy = artifacts.require("ERC1967Proxy");

const QueryMTPValidatorOffChain = artifacts.require("QueryMTPValidatorOffChain");
const QuerySigValidatorOffChain = artifacts.require("QuerySigValidatorOffChain");
const CredentialAtomicQuerySigValidator = artifacts.require("CredentialAtomicQuerySigValidator");
const CredentialAtomicQueryMTPValidator = artifacts.require("CredentialAtomicQueryMTPValidator");

export = async (deployer: Deployer, logger: Logger) => {
const config: Config = parseConfig();
Expand Down Expand Up @@ -39,9 +39,9 @@ export = async (deployer: Deployer, logger: Logger) => {
let validatorsInfo;

if (config.validatorContractInfo.isSigValidator) {
validatorsInfo = ["QuerySigValidatorOffChain", (await QuerySigValidatorOffChain.deployed()).address];
validatorsInfo = ["QuerySigValidatorOnChain", (await CredentialAtomicQuerySigValidator.deployed()).address];
} else {
validatorsInfo = ["QueryMTPValidatorOffChain", (await QueryMTPValidatorOffChain.deployed()).address];
validatorsInfo = ["QueryMTPValidatorOnChain", (await CredentialAtomicQueryMTPValidator.deployed()).address];
}

logger.logContracts(
Expand Down
8 changes: 4 additions & 4 deletions deploy/5_set_zkp_query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Config, parseConfig } from "@/deploy/helpers/config_parser";
import { AGE_VERIFY_REQUEST_ID } from "@/test/helpers/constants";

const QueryVerifier = artifacts.require("QueryVerifier");
const QueryMTPValidatorOffChain = artifacts.require("QueryMTPValidatorOffChain");
const QuerySigValidatorOffChain = artifacts.require("QuerySigValidatorOffChain");
const CredentialAtomicQuerySigValidator = artifacts.require("CredentialAtomicQuerySigValidator");
const CredentialAtomicQueryMTPValidator = artifacts.require("CredentialAtomicQueryMTPValidator");

const Operators = {
NOOP: 0, // No operation, skip query verification in circuit
Expand All @@ -23,9 +23,9 @@ export = async (deployer: Deployer, logger: Logger) => {
let validator;

if (config.validatorContractInfo.isSigValidator) {
validator = await QuerySigValidatorOffChain.deployed();
validator = await CredentialAtomicQuerySigValidator.deployed();
} else {
validator = await QueryMTPValidatorOffChain.deployed();
validator = await CredentialAtomicQueryMTPValidator.deployed();
}

const circuitId = await validator.getCircuitId();
Expand Down
Loading

0 comments on commit f03d059

Please sign in to comment.