Skip to content

Commit

Permalink
Merge pull request #3 from rarimo/reference/polygonid-integration
Browse files Browse the repository at this point in the history
PolygonID x Rarimo
  • Loading branch information
ihordiachenko authored Dec 19, 2023
2 parents fdc24d9 + 95230b9 commit eaedf28
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Reference:
- Added the "Polygon ID State Replication" page;
- Use Cases:
- Added the "Identity State Replication" doc;
- How-to-Guides:
Expand Down
1 change: 1 addition & 0 deletions docs/reference/api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ GitHub: https://github.com/rarimo/issuer
| Mainnet | https://api.robotornot.rarimo.com |
|----------|----------------------------|
| Testnet | https://api.robotornot.mainnet-beta.rarimo.com |

234 changes: 234 additions & 0 deletions docs/reference/polygonid-state-replication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
---
sidebar_label: Polygon ID State Replication
---

# Polygon ID State Replication

This page contains technical resources related to the [Polygon ID State Replication](/use-cases/polygon-id).

## Demo DApp

Users can check out how the state replication works using our demo DApp. Leveraging the state replication lets users submit a Polygon ID zero-knowledge proof on Ethereum. Users get an SBT as a reward.

Testnet(Sepolia): https://polygon.mainnet-beta.rarimo.com/

## Identity Relayer

This service replicates GIST roots and identity states on demand.
Call it before submitting proof on the destination chain.

- Github: https://github.com/rarimo/identity-relayer-svc
- API Reference: https://rarimo.github.io/rarimo-core/docs/common/bridging/002-identity.html
- Testnet URI: https://api.mainnet-beta.rarimo.com

### Relayer endpoints

To perform state publishing, you can execute POST `/integrations/relayer/state/relay` request with the following body:

```json
{
"chain": "Ethereum",
"hash": "0x212bc6f8194aa63eee97b0566b7cd65c66bb57cc4936c11e611f1042bb0b7118",
"waitConfirm": true
}
```

To perform GIST publishing, you can execute POST `/integrations/relayer/gist/relay` request with the following body:

```json
{
"chain": "Ethereum",
"hash": "0x1e4b74c14388fbfca27496828d24c248637792eb0286e7519860abb3ec01bc70",
"waitConfirm": true
}
```

- `"chain": "chain_name"` - chain, to which the state (or gist) will be relayed;
- `"hash": "0x..."` - hash of the state (or gist) to relay. Same as on the state contract in 0x... hex format;
- `"waitConfirm": true` indicates whether the request should wait until the transaction is included in the block (`false` by default);

The response codes:
- `200` - successful relay, body contains tx hash;
- `404` - the state is not transferred yet; try to repeat the request later;
- `400` - state has been relayed before;

## Smart Contracts

<!-- TODO: Add mainnet contracts addresses -->

### `LightweightStateV2`

It's a modified state contract meant for the destination chains.
It checks a TSS from the Rarimo validators instead of a ZKP to transit the state and only holds a partial history.
The relayer service lazily updates the contract whenever a user wants to submit ZKP on a particular chain.

#### Deployments

|Chain| ChainID| Address|
| --- | --- | --- |
| Sepolia | `11155111` | `0x4EaEdFbD2156f5D77b11c4fE073032c4D90Dd315` \([Etherscan](https://sepolia.etherscan.io/address/0x4EaEdFbD2156f5D77b11c4fE073032c4D90Dd315)\) |

#### Interface

```solidity
contract LightweightStateV2 is ILightweightStateV2, UUPSSignableUpgradeable, Signers {
address public override sourceStateContract;

uint256 internal _currentGistRoot;

mapping(uint256 => GistRootData) internal _gistsRootData;

mapping(uint256 => IdentityInfo) internal _identitiesInfo;

function signedTransitGISTData(
uint256 prevGist_,
GistRootData calldata gistData_,
bytes calldata proof_
) external override {
// ...

emit SignGISTDataTransited(gistData_.root, prevGist_);
}

function signedTransitStateData(
uint256 prevState_,
StateData calldata stateData_,
bytes calldata proof_
) external override {
// ...

emit SignStateDataTransited(stateData_.id, stateData_.state, prevState_);
}
}

```

- `sourceStateContract` address of the state contract on the source chain (Rarimo);
- `_currentGistRoot` the latest transferred GIST root;
- `_gistsRootData` mapping of the GIST roots to their data.
Data stores two roots, one that replaced the other, timestamp and block number;
- `_identitiesInfo` mapping of the identity IDs to the information about this identity.
Information has the latest identity state and the history of the states with timestamps;
- `signedTransitGISTData()` adds the GIST root to the history and changes the current root variable if the proposed one is newer;
- `signedTransitStateData(...)` adds the state to the history and sets the last state of the identity to the provided one if it's newer;

Both functions require proof of change TSS of Rarimo signature providers.
Also, core functions emit events, which contain the data about changes:
- `SignGISTDataTransited` contains the data about roots, the previous one and the provided one;
- `SignStateDataTransited` contains the provided identity state, previous state, and identity ID;

Full implementation can be found [here](https://github.com/rarimo/polygonid-integration-contracts/blob/master/contracts/LightweightStateV2.sol).

### `QueryVerifier`

It's an implementation of a verifier contract that inherits Iden3 [ZKPVerifier](https://github.com/iden3/contracts/blob/master/contracts/verifiers/ZKPVerifier.sol) that mints an SBT.
It is configured to work with the KYCAge demo credential.

#### Deployments

|Chain| ChainID| Address|
| --- | --- | --- |
| Sepolia | `11155111` | `0xb95734f64f242E976E155594E1E15D39700Cbb26` \([Etherscan](https://sepolia.etherscan.io/address/0xb95734f64f242E976E155594E1E15D39700Cbb26)\) |

#### Interface

```solidity
contract QueryVerifier is IQueryVerifier, ZKPVerifier {
uint256 public constant AGE_VERIFY_REQUEST_ID = 1;

IVerifiedSBT public override sbtContract;

mapping(address => uint256) public override addressToUserId;

mapping(uint256 => VerificationInfo) internal _verificationsInfo;

function _beforeProofSubmit(
uint64,
uint256[] memory inputs_,
ICircuitValidator
) internal override {
require(
!isUserVerified(_getIdentityId(inputs_)),
"QueryVerifier: identity with this identifier has already been verified"
);
require(
addressToUserId[msg.sender] == 0,
"QueryVerifier: current address has already been used to verify another identity"
);
}

function _afterProofSubmit(
uint64,
uint256[] memory inputs_,
ICircuitValidator
) internal override {
uint256 tokenId_ = sbtContract.nextTokenId();
uint256 userId_ = _getIdentityId(inputs_);

_verificationsInfo[userId_] = VerificationInfo(msg.sender, tokenId_);
addressToUserId[msg.sender] = userId_;

sbtContract.mint(msg.sender);

emit Verified(userId_, msg.sender, tokenId_);
}
}
```

- `AGE_VERIFY_REQUEST_ID` hard-coded KYC demo request ID;
- `sbtContract` address of the SBT contract, which will be called to mint Soulbound token;
- `addressToUserId` mapping of addresses to user's identity ID;
- `_verificationsInfo` mapping of user's identity ID to the verification information, which contains the prover address and minted token ID;
- `_beforeProofSubmit` hook that performs some necessary security checks;
- `_afterProofSubmit` another hook, which mints the SBT in case of valid verification;

The function that verifies the ZKP - `verify(...)` is inherited from the [ZKPVerifier](https://github.com/iden3/contracts/blob/master/contracts/verifiers/ZKPVerifier.sol) contract.

Full implementation can be found [here](https://github.com/rarimo/polygonid-integration-contracts/blob/master/contracts/QueryVerifier.sol).

### `VerifiedSBT`

The SBT is awarded to users who complete the Polygon ID x Rarimo demo.

#### Deployments

|Chain| ChainID| Address|
| --- | --- | --- |
| Sepolia | `11155111` | `0x8A55c9CfDCbCeDcA1A543295a3F54351C335A20f` \([Etherscan](https://sepolia.etherscan.io/address/0x8A55c9CfDCbCeDcA1A543295a3F54351C335A20f)\) |

#### Interface

```solidity
contract VerifiedSBT is
IVerifiedSBT,
UUPSUpgradeable,
ERC721EnumerableUpgradeable,
OwnableUpgradeable
{
address public override verifier;
uint256 public override nextTokenId;
string public override tokensURI;

// ...

function mint(address recipientAddr_) external override onlyVerifier {}

function _beforeTokenTransfer(
address from_,
address to_,
uint256 firstTokenId_,
uint256 batchSize_
) internal override {
// ...
}
}
```

- `verifier` address of the verifier's (`QueryVerifier`) contract;
- `nextTokenId` nonce that is incremented each time a new SBT is created;
- `tokensURI` token's picture URI;
- `onlyVerifier()` modifier that allows calls only by the verifier contract;
- `mint(address)` mints the SBT for the given address;
- `_beforeTokenTransfer(...)` prevents the token from being transferred (only burn and mint are available);

Full implementation can be found [here](https://github.com/rarimo/polygonid-integration-contracts/blob/master/contracts/VerifiedSBT.sol).
4 changes: 4 additions & 0 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ const sidebars = {
type: "doc",
id: "reference/proof-of-humanity",
},
{
type: "doc",
id: "reference/polygonid-state-replication",
},
{
type: "doc",
id: "reference/api",
Expand Down

0 comments on commit eaedf28

Please sign in to comment.