mirror of
https://github.com/CryptKeeperZK/Docs.git
synced 2026-01-09 23:17:55 -05:00
200 lines
4.8 KiB
Markdown
200 lines
4.8 KiB
Markdown
# 🐰 Zkitter examples
|
|
|
|
[Zkitter](https://www.zkitter.com/explore/) is an example of how a live dapp integrates with CryptKeeper and connects to the extension.  
|
|
|
|
The `connectZKPR` function connects to an existing identity by using the `zkpr.connect()` method. The returned client is then used to instantiate a new `ZKPR` object. Then it listens for events such as `logout` and `identityChanged` and dispatches actions accordingly.
|
|
|
|
```typescript
|
|
export const connectZKPR =
|
|
() => async (dispatch: ThunkDispatch<any, any, any>, getState: () => AppRootState) => {
|
|
dispatch(setLoading(true));
|
|
|
|
|
|
try {
|
|
let id: Identity | null = null;
|
|
|
|
|
|
// @ts-ignore
|
|
if (typeof window.zkpr !== 'undefined') {
|
|
// @ts-ignore
|
|
const zkpr: any = window.zkpr;
|
|
const client = await zkpr.connect();
|
|
const zkprClient = new ZKPR(client);
|
|
|
|
|
|
zkprClient.on('logout', async data => {
|
|
const {
|
|
worker: { selected, identities },
|
|
} = getState();
|
|
|
|
|
|
dispatch(disconnectZKPR());
|
|
|
|
|
|
const [defaultId] = identities;
|
|
if (defaultId) {
|
|
postWorkerMessage(
|
|
selectIdentity(
|
|
defaultId.type === 'gun' ? defaultId.publicKey : defaultId.identityCommitment
|
|
)
|
|
);
|
|
} else {
|
|
postWorkerMessage(setIdentity(null));
|
|
}
|
|
});
|
|
|
|
|
|
zkprClient.on('identityChanged', async data => {
|
|
const idCommitment = data && BigInt('0x' + data).toString();
|
|
const {
|
|
worker: { identities },
|
|
} = getState();
|
|
|
|
|
|
dispatch(setIdCommitment(''));
|
|
|
|
|
|
if (idCommitment) {
|
|
// @ts-ignore
|
|
dispatch(setIdCommitment(idCommitment));
|
|
// @ts-ignore
|
|
const id: any = await maybeSetZKPRIdentity(idCommitment);
|
|
if (!id) {
|
|
const [defaultId] = identities;
|
|
if (defaultId) {
|
|
postWorkerMessage(
|
|
selectIdentity(
|
|
defaultId.type === 'gun' ? defaultId.publicKey : defaultId.identityCommitment
|
|
)
|
|
);
|
|
} else {
|
|
postWorkerMessage(setIdentity(null));
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
localStorage.setItem('ZKPR_CACHED', '1');
|
|
|
|
|
|
const idCommitmentHex = await zkprClient.getActiveIdentity();
|
|
const idCommitment = idCommitmentHex && BigInt('0x' + idCommitmentHex).toString();
|
|
|
|
|
|
if (idCommitment) {
|
|
dispatch(setIdCommitment(idCommitment));
|
|
id = await maybeSetZKPRIdentity(idCommitment);
|
|
}
|
|
|
|
|
|
dispatch(setZKPR(zkprClient));
|
|
}
|
|
|
|
|
|
dispatch(setLoading(false));
|
|
|
|
|
|
return id;
|
|
} catch (e) {
|
|
dispatch(setLoading(false));
|
|
throw e;
|
|
}
|
|
};
|
|
```
|
|
|
|
{% embed url="https://github.com/zkitter/ui/blob/main/src/ducks/zkpr.ts#L45-L126" %}
|
|
|
|
 
|
|
|
|
 
|
|
|
|
An example of how Zkitter generates proofs: 
|
|
|
|
```typescript
|
|
const identityPathIndex = merkleProof!.pathIndices;
|
|
|
|
if (
|
|
!identityCommitment ||
|
|
!identityPathElements ||
|
|
!identityPathIndex ||
|
|
!identityTrapdoor ||
|
|
!identityNullifier
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
const { messageId, hash, ...json } = post.toJSON();
|
|
|
|
const epoch = getEpoch();
|
|
const externalNullifier = genExternalNullifier(epoch);
|
|
const signal = messageId;
|
|
const rlnIdentifier = await sha256('zkpost');
|
|
const xShare = RLN.genSignalHash(signal);
|
|
const witness = RLN.genWitness(
|
|
identitySecretHash!,
|
|
merkleProof!,
|
|
externalNullifier,
|
|
signal,
|
|
BigInt('0x' + rlnIdentifier)
|
|
);
|
|
const { proof, publicSignals } = await RLN.genProof(
|
|
witness,
|
|
`${config.indexerAPI}/circuits/rln/wasm`,
|
|
`${config.indexerAPI}/circuits/rln/zkey`
|
|
);
|
|
```
|
|
|
|
{% embed url="https://github.com/zkitter/ui/blob/main/src/ducks/drafts.ts#L139-L169" %}
|
|
|
|
  
|
|
|
|
An example of how Zkitter verifies proofs: 
|
|
|
|
```typescript
|
|
if (result) {
|
|
logger.debug('post already exist', {
|
|
messageId,
|
|
origin: 'gun',
|
|
});
|
|
return;
|
|
}
|
|
|
|
|
|
if (!creator && !data) {
|
|
return;
|
|
}
|
|
|
|
|
|
try {
|
|
if (data) {
|
|
const proof = JSON.parse(data.proof);
|
|
const publicSignals = JSON.parse(data.publicSignals);
|
|
|
|
|
|
let verified = false;
|
|
|
|
|
|
if (!data.x_share) {
|
|
verified = await Semaphore.verifyProof(vKey as any, {
|
|
proof,
|
|
publicSignals,
|
|
});
|
|
|
|
|
|
if (!verified) return;
|
|
} else {
|
|
verified = await this.call('zkchat', 'verifyRLNProof', {
|
|
epoch: data.epoch,
|
|
proof,
|
|
publicSignals,
|
|
x_share: data.x_share,
|
|
});
|
|
```
|
|
|
|
{% embed url="https://github.com/zkitter/zkitterd/blob/main/src/services/gun.ts#L277-L305" %}
|
|
|
|
|
|
|
|
 
|