# Create and issue ZK certificate

There are currently three types of certificates, each with distinct input requirements:

1. [zkkyc-gip-1](https://docs.galactica.com/galactica-developer-documentation/guardian-guide/create-and-issue-zkkyc/zkkyc-gip-1 "mention"): This type involves the use of government-issued documents and a strictly defined set of data.
2. [arbitrary-zk-data-certificate-gip-2](https://docs.galactica.com/galactica-developer-documentation/guardian-guide/create-and-issue-zkkyc/arbitrary-zk-data-certificate-gip-2 "mention"): This type is flexible and can work with almost any type of data.
3. [zkkyc-gip-1-1](https://docs.galactica.com/galactica-developer-documentation/guardian-guide/create-and-issue-zkkyc/zkkyc-gip-1-1 "mention"): This type of certificate contains data about one's X account data.

Upon validating a user's request and verifying the provided data, Guardians can create a zero-knowledge (zk) certificate and issue it on the Galactica blockchain.

The process for issuing an arbitrary data certificate is similar to the issuance of a zkKYC certificate described below, with the only difference being the input data.

{% hint style="warning" %}
Make sure that you have an SDK installed. Please, refer to [#installation-instructions](https://docs.galactica.com/galactica-developer-documentation/setup-to-become-a-guardian#installation-instructions "mention") if you haven't done it yet.
{% endhint %}

### Expiration Date

All kinds of ZK Certificates contain an expiration date. After that date the user can no longer use it or the verification SBTs created with it. Then an new new ZK Certificate needs to be issued with the Guardian.

### Holder Commitment

The user provides a [#holder-commitment](https://docs.galactica.com/galactica-developer-documentation/guardian-guide/zkkyc-gip-1#holder-commitment "mention") to the Guardian. It links the resulting ZK Certificate to the user's address while keeping the link private.

## Creating a zkCertificate

Prepare JSON files containing [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#personal-details](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#personal-details "mention") and the [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#holder-commitment](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#holder-commitment "mention"). The expiration date will be passed via command line parameters to the CLI.

{% tabs %}
{% tab title="TypeScript" %}
Run the following command:

{% code overflow="wrap" %}

```sh
yarn hardhat createZkCertificate --holder-file example/holderCommitment.json --data-file example/test.json --registry-address 0xD95efF72F06079DEcE33b18B165fc3A7a4bdc1fD --expiration-date 2344658820 --network reticulum --zk-certificate-type zkKYC
```

{% endcode %}

The command generates the signature of the Guardian using the Hardhat framework.

The command provides the resulting certificate in the console output.

{% hint style="info" %}
If you additionally provide `--registry-address` and `--network` flags, you can immediately issue created certificate.
{% endhint %}
{% endtab %}

{% tab title="GoLang" %}
Run the following command:

{% code overflow="wrap" %}

```sh
galactica-guardian createZKCert -s gip1 -H holder_commitment.json -i certificate_inputs.json -k provider_private_key.hex -e "2030-01-01T00:00:00Z"
```

{% endcode %}

CLI requires to provide the Guardian's [EdDSA private key](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/setup-to-become-a-guardian.md#key-pair) (via `-k` flag) to sign the certificate.

The command saves the resulting certificate to file named `certificate.json` (you can customise output location with `-o` flag).

{% hint style="warning" %}
The resulting certificate is not issued yet. For the instructions on how to issue the certificate, proceed to the section [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#issuing-zkCertificate-on-chain](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#issuing-zkCertificate-on-chain "mention").
{% endhint %}
{% endtab %}
{% endtabs %}

The signature of the Guardian is generated using explicit private key via the SDK. You can fork the code if you want to use a hardware or multi-sig wallet instead.

This completes the following tasks:

* Collect input data
* Hash data into a DID that uniquely identifies the zkCertificate
* Signs the zkCertificate with the providers EdDSA key

Guardians need to store the resulting zkCertificateType in a [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/setup-to-become-a-guardian.md#data-storage-for-compliance](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/setup-to-become-a-guardian.md#data-storage-for-compliance "mention").

## Issuing a zkCertificateType on-chain

{% hint style="warning" %}
This action sends a transaction to the blockchain. Make sure the wallet that you will use to send this transaction has sufficient GNET to pay for gas fees.
{% endhint %}

To issue the zkCertificateType on the Galactica blockchain means to insert the DID of this certificate into the smart contract registry. That contract contains a data structure called Merkle tree. With it users can prove that their zkCertificateType has been added without disclosing the DID or any other personal data.

The method for issuing is `addZkCertificate` of the [zkCertificateType registry](https://github.com/Galactica-corp/galactica-monorepo/blob/main/packages/zk-certificates/contracts/ZkCertificateRegistry.sol). Only addresses that were added to the zkCertificate guardian whitelist can call this method (see [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/setup-to-become-a-guardian.md#obtaining-a-license](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/setup-to-become-a-guardian.md#obtaining-a-license "mention")). Because the zkCert registry is based on a sparse merkle tree, the smart contract has a modification queue that prevents concurrency conflicts during modification. Update requests are registered using `registerToQueue(bytes32 zkCertificateHash)`. `checkZkCertificateHashInQueue(bytes32 zkCertificateHash)` gives feedback on when you are the first in the queue and can call `addZkCertificate`. The queue can introduce wait times if guardians do not execute the modifications directly when it is their turn. The zkCert registry has a `queueExpirationTime` parameter to skip unused or faulty queue entries.

The Guardian SDKs take care of the queueing for you using the methods listed below.

If you want to (re-)issue previously or separately created zkCertificateTypes, you can parameterize and run the following script:

{% tabs %}
{% tab title="TypeScript" %}
We recommend using the `createZkCertificate` task used in [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#creating-a-zkCertificate](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#creating-a-zkCertificate "mention") to issue the zkCertificate on-chain.

{% hint style="info" %}
Make sure to provide the `--registry-address`, `--zk-certificate-type`,`and`--network\` flags.
{% endhint %}
{% endtab %}

{% tab title="GoLang" %}
Run the following command:

{% code overflow="wrap" %}

```sh
galactica-guardian issueZKCert -c zkcert.json -k provider_private_key.hex -r 0x4De49e2047eE726B833fa815bf7392958245832d --rpc-url 
https://evm-rpc-http-andromeda.galactica.com
```

{% endcode %}

CLI requires to provide the Guardian's Ethereum private key (via `-k` flag) to sign the resulting transaction.

The command saves the resulting certificate to file named `issued-certificate.json` (you can customise output location with `-o` flag).

{% hint style="info" %}
Currently to generate a Merkle tree proof it is required to query on-chain data. To significantly speed up this process we advise to provide the `registry-events-start` flag. It's value should be a block number in which you issed the first certificate or the block number when the registry was deployed.
{% endhint %}
{% endtab %}
{% endtabs %}

**Whey the issued certificate is a zkKYC, the on-chain registry limits the user to one salt hash for the** [dapp-specific-humanid](https://docs.galactica.com/galactica-developer-documentation/galactica-concepts/zero-knowledge-kyc/dapp-specific-humanid "mention"). Details can be found in [#registration-of-the-salt-for-the-humanid](https://docs.galactica.com/galactica-developer-documentation/galactica-concepts/zero-knowledge-kyc/dapp-specific-humanid#registration-of-the-salt-for-the-humanid "mention").\
If the zkKYC can not be issued due to a salt hash mismatch, the guardian should ask the user to switch to the same account as used before to hold zkKYCs. If this is not possible, the guardian can inform about the zkKYCs locking the salt hash and how they can be revoked or how long they take to expire.

## **Revoking a zkCertificate**

{% hint style="warning" %}
This action sends a transaction to the blockchain. Make sure the wallet that you will use to send this transaction has sufficient GNET to pay for gas fees.
{% endhint %}

In the zkCertificate repository, a Guardian can revoke zkCertificate with the following command. To revoke the certificate, Guardian needs to have access to the issued zkCertificate file. The command then calls the method `revokeZkCertificate`of the [zkCertificate registry](https://github.com/Galactica-corp/galactica-monorepo/blob/main/packages/zk-certificates/contracts/ZkCertificateRegistry.sol). Only the Guardian that issued this zkCertificate can call this method.

{% tabs %}
{% tab title="TypeScript" %}
Run the following command:

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong>yarn hardhat revokeZkCertificate --leaf-hash 21748663475365191123601746644146228783455921656164300532651112457689544266821 --index 2 --registry-address 0xAbb654092b5BCaeca2E854550c5C972602eF7dA8 --network galaAndromeda
</strong></code></pre>

Currently, Guardian needs to access the zkCertificate and directly provide leaf hash and leaf index as command line parameters.
{% endtab %}

{% tab title="GoLang" %}
Run the following command:

{% code overflow="wrap" %}

```sh
galactica-guardian revokeZKCert -c zkcert.json -k provider_private_key.hex -r 0x4De49e2047eE726B833fa815bf7392958245832d --rpc-url 
https://evm-rpc-http-andromeda.galactica.com
```

{% endcode %}

CLI accepts a file containing the zkCertificate (via flag `-c`) and reads all the required certificate properties automatically.

CLI requires to provide the Guardian's Ethereum private key (via `-k` flag) to sign the resulting transaction.

{% hint style="info" %}
Currently to generate a Merkle tree proof it is required to query on-chain data. To significantly speed up this process we advise to provide the `registry-events-start` flag. It's value should be a block number in which you issed the first certificate or the block number when the registry was deployed.
{% endhint %}
{% endtab %}
{% endtabs %}

## Providing a zkCertificate to user

After creating and issuing a zkCertificate, the user still must import it in the wallet to be able to use it. This step is necessary because the user needs to provide personal details, the Guardian signature and DID as private inputs when generating a zero-knowledge proof.

Therefore the Guardian should send the created zkCertificate as file to the user. This has to be done in the encrypted JSON format. For encryption, an ECDSA key pair and the [@metamask/eth-sig-util/encryptSafely](https://metamask.github.io/eth-sig-util/latest/functions/encryptSafely.html) method are used. The public ECDSA key has been provided by the user's snap together with the holder commitment.

Providing a download option or sending it via mail are two possible ways to send the file to the user.

{% tabs %}
{% tab title="TypeScript" %}
CLI automatically generates an encrypted certificate at [https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#creating-a-zkCertificate](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/create-and-issue-zkkyc/create-and-issue-zkCertificate.md#creating-a-zkCertificate "mention") step.
{% endtab %}

{% tab title="GoLang" %}
Run the following command:

{% code overflow="wrap" %}

```sh
galactica-guardian encryptZKCert -c zkcert.json -H holder_commitment.json
```

{% endcode %}

The command saves the resulting certificate to file named `encrypted-certificate.json` (you can customise output location with `-o` flag).
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
To import the created certificate to the snap, user must visit url `<galactica-app>/?showWideUploading=true`, where `<galactica-app>` is a URL of the Galactica web application of the corresponding network. For example, the DevNet application URL is listed here:[https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/devnet-andromeda/README.md#galactica-web-application](https://github.com/Galactica-corp/Documentation/blob/master/guardian-guide/devnet-andromeda/README.md#galactica-web-application "mention").
{% endhint %}
