UNPKG

@unirep/core

Version:

Client library for protocol related functions which are used in UniRep protocol.

316 lines (315 loc) 14.2 kB
import { ethers } from 'ethers'; import { DB } from 'anondb'; import { Identity } from '@semaphore-protocol/identity'; import { Prover, ReputationProof, EpochKeyProof, SignupProof, UserStateTransitionProof, EpochKeyLiteProof } from '@unirep/circuits'; import { Synchronizer } from './Synchronizer'; /** * The user state object is used to manage user state for an attester. * The state is backed by an [anondb](https://github.com/vimwitch/anondb) instance. * @example * ```ts * import { UserState } from '@unirep/core' * import { defaultProver } from '@unirep/circuits/provers/defaultProver' * import { Identity } from '@semaphore-protocol/identity' * * const id = new Identity() * const state = new UserState({ * prover: defaultProver, // a circuit prover * unirepAddress: '0xaabbccaabbccaabbccaabbccaabbccaabbccaaaa', * provider, // an ethers.js provider * id, * }) * * // or, initialize with an existing synchronizer object * const state = new UserState({ * synchronizer, * id, * prover: defaultProver, // a circuit prover * }) * * // start the synchoronizer deamon * await state.start() * await state.waitForSync() * * // stop the synchronizer deamon * state.stop() * ``` */ export default class UserState { private _prover; private _id; private _sync; private _chainId; private _db; /** * The [Semaphore](https://semaphore.pse.dev/) identity commitment of the user. */ get commitment(): bigint; /** * The [Semaphore](https://semaphore.pse.dev/) identity of the user. */ get id(): Identity; /** * The underlying synchronizer object. */ get sync(): Synchronizer; /** * The prover object. */ get prover(): Prover; /** * The current chain ID of UniRep contract. */ get chainId(): number; /** * Read the database object. */ get db(): DB; constructor(config: { synchronizer?: Synchronizer; db?: DB; attesterId?: bigint | bigint[]; unirepAddress?: string; provider?: ethers.providers.Provider; id: Identity; prover: Prover; }); /** * Start the synchronizer daemon. * Start polling the blockchain for new events. If we're behind the HEAD block we'll poll many times quickly */ start(): Promise<void>; /** * Wait for the synchronizer to sync up to a certain block. * By default this will wait until the current latest known block (according to the provider). * @param blockNumber The block number to be synced to. */ waitForSync(blockNumber?: number): Promise<void>; /** * Stop synchronizing with Unirep contract. */ stop(): void; /** * Query the current database if the [Semaphore](https://semaphore.pse.dev/) identity commitment is stored. * @param attesterId The attester to be queried. Default: `this.attesterId`. * @returns True if user has signed up in unirep contract, false otherwise. */ hasSignedUp(attesterId?: bigint | string): Promise<boolean>; /** * Query the current database for a user's signup event or latest user state transition [nullifier](https://developer.unirep.io/docs/protocol/nullifiers). * @param attesterId The attester to be queried. Default: `this.attesterId` * @returns The latest epoch where a user performed a user state transition. */ latestTransitionedEpoch(attesterId?: bigint | string): Promise<number>; /** * Get the latest global state tree leaf index for an epoch. * @param epoch Get the global state tree leaf index of the given epoch. Default: current epoch. * @param attesterId The attester to be queried. Default: `this.attesterId` * @returns The the latest state tree leaf index for an epoch. */ latestStateTreeLeafIndex(epoch?: number, attesterId?: bigint | string): Promise<number>; /** * Get epoch keys for the current user, for an epoch. * If a `nonce` value is supplied the return value will be a single epoch key. * Otherwise an array of all epoch keys will be returned. * * If no `epoch` is supplied the current epoch will be used (as determined by `synchronizer.calcCurrentEpoch`). * @param epoch The epoch to be queried. Default: current epoch. * @param nonce The specified epoch key nonce. Default: `0`. * @param attesterId The attester to be queried. Default: `this.attesterId` * @returns An epoch key or an array of epoch keys. */ getEpochKeys(epoch?: bigint | number, nonce?: number, attesterId?: bigint | string): bigint | bigint[]; /** * This function is used to parse replacement data field to be `index` and `data`. See [replacement data field](https://developer.unirep.io/docs/protocol/data#replacement-field). * @param replData The raw data which is processed on-chain. * @returns The parsed data and the data index (nonce). */ parseReplData(replData: bigint): { data: bigint; nonce: bigint; }; /** * @private * Update user state data. * @param data The latest transitioned data. * @param latestTransitionedEpoch The latest found transitioned epoch. * @param attesterId The attester ID. */ private _updateData; /** * Get the data for a user up to and including the provided epoch. * By default data up to and including the current epoch is returned. * * :::tip * If you want to make a proof of data make sure to use `getProvableData`. * Data can only be proven once it has been included in a state tree leaf. * Learn more about reputation proofs [here](https://developer.unirep.io/docs/circuits-api/classes/src.ReputationProof.md). * ::: * @param toEpoch The latest epoch that the reputation is accumulated. Default: current epoch. * @param attesterId The attester to be queried. Default: `this.sync.attesterId` * @param fromEpoch The epoch to start querying from. Default: `0`. * @returns The data object */ getData: (toEpoch?: number, attesterId?: bigint | string) => Promise<bigint[]>; /** * Get the data that can be proven by the user using a state tree leaf. * This is the data up to, but not including, the epoch the user has transitioned into. * @param attesterId The attester to be queried. Default: `this.attesterId` * @returns The data object */ getProvableData(attesterId?: bigint | string): Promise<bigint[]>; /** * Get the pending changes to the data owned by an epoch key. * @param epochKey The epoch key to be queried. * @param epoch The epoch of the epoch key to be queried. * @param attesterId The attester to be queried. Default: `this.attesterId` * @returns The data object. */ getDataByEpochKey: (epochKey: bigint | string, epoch: number, attesterId?: bigint | string) => Promise<any[]>; /** * @private * Check if epoch key nonce is valid. Throws an error if the epoch key nonce is invalid. * @param epochKeyNonce The input epoch key nonce to be checked. */ private _checkEpkNonce; /** * @private * Check if a synchronizer is set. Throws an error if a synchronizer is not set. */ private _checkSync; /** * @private * Check if a chain ID is set. If a chain ID is not set, it queries the provider and sets chain ID. */ private _checkChainId; /** * @private * Check if the input exceeds the maximum bit * @param input The input value * @param bit The bit number */ private _checkBit; /** * Get the index of epoch key among all attestations. * @param epoch The epoch of the epoch key to be queried. * @param epochKey The epoch key to be queried. * @param attesterId The attester to be queried. * @returns The index of the epoch key. */ getEpochKeyIndex: (epoch: number, epochKey: bigint | string, attesterId: bigint | string) => Promise<number>; /** * Generate a user state transition proof. Returns a [`UserStateTransitionProof`](https://developer.unirep.io/docs/circuits-api/classes/src.UserStateTransitionProof.md). * @param options.toEpoch `toEpoch` is used to indicate in which epoch the proof will be used. Default: current epoch. * @param options.attesterId `attesterId` is used to generate proof for certain attester. Default: `this.attesterId`. * @returns The `UserStateTransitionProof` object. * @example * ```ts * const { publicSignals, proof } = await userState.genUserStateTransitionProof() * ``` */ genUserStateTransitionProof: (options?: { toEpoch?: number; attesterId?: bigint | string; }) => Promise<UserStateTransitionProof>; /** * Generate a proof of reputation. Returns a [`ReputationProof`](https://developer.unirep.io/docs/circuits-api/classes/src.ReputationProof.md). * :::danger * **Please avoid assigning the `minRep = data[0] - data[1]` or `maxRep = data[1] - data[0]`.**<br/> * The proof could allow a user to accidentally publish their overall reputation (i.e. `data[0]-data[1]`). * Depending on the circumstances (such as the length of the attestation history) this could reveal a user’s epoch key(s) as well. * ::: * @param options.epkNonce The nonce determines the output of the epoch key. Default: `0`. * @param options.minRep The amount of reputation that user wants to prove. It should satisfy: `posRep - negRep >= minRep`. Default: `0` * @param options.maxRep The amount of reputation that user wants to prove. It should satisfy: `negRep - posRep >= maxRep`. Default: `0` * @param options.graffiti The graffiti that user wants to prove. It should satisfy: `graffiti == (data[SUM_FIELD_COUNT] / (2 ** REPL_NONCE_BITS))`. Default: `0`. * @param options.proveZeroRep Indicates if user wants to prove `posRep - negRep == 0`. Default: `0`. * @param options.revealNonce Indicates if user wants to reveal epoch key nonce. Default: `false`. * @param options.data Indicates if user wants to endorse a 253-bits data. Default: `0`. * @param options.attesterId `attesterId` is used to generate proof for certain attester. Default: `this.attesterId` * @returns The reputation proof of type `ReputationProof`. * @example * ```ts * const {publicSignals, proof} = await userState.genProveReputationProof({ * minRep: 3, * graffiti: '1234', * }) * ``` */ genProveReputationProof: (options: { epkNonce?: number; minRep?: number | bigint | string; maxRep?: number | bigint | string; graffiti?: bigint | string; proveZeroRep?: boolean; revealNonce?: boolean; data?: bigint | string; attesterId?: bigint | string; }) => Promise<ReputationProof>; /** * Generate a proof that can be used to signup. Returns a [`SignupProof`](https://developer.unirep.io/docs/circuits-api/classes/src.SignupProof.md) * @param options.epoch Indicates in which epoch the proof will be used. Default: current epoch. * @param options.attesterId Indicates for which attester the proof will be used. Default: `this.attesterId` * @returns The sign up proof of type `SignUpProof`. * @example * ```ts * const { publicSignals, proof } = await userState.genUserSignUpProof() * ``` */ genUserSignUpProof: (options?: { epoch?: number; attesterId?: bigint | string; }) => Promise<SignupProof>; /** * Generate a proof that a user controls an epoch key in a certain epoch. * Optionally provide a data value to sign. * Returns an [`EpochKeyProof`](https://developer.unirep.io/docs/circuits-api/classes/src.EpochKeyProof.md). * @param options.nonce The specified epoch key nonce. Default: `0`. * @param options.epoch The specified epoch. Default: current epoch. * @param options.data Indicates if user wants to endorse a 253-bits data. Default: `0` * @param options.revealNonce Indicates if user wants to reveal epoch key nonce. Default: `false`. * @param options.attesterId Indicates for which attester the proof will be used. Default: `this.attesterId` * @returns The epoch key proof of type `EpochKeyProof`. * @example * ```ts * const { publicSignals, proof } = await userState.genEpochKeyProof({ * nonce: 1 * }) * ``` */ genEpochKeyProof: (options?: { nonce?: number; epoch?: number; data?: bigint; revealNonce?: boolean; attesterId?: bigint | string; }) => Promise<EpochKeyProof>; /** * Generate a proof that a user controls an epoch key in a certain epoch. * Optionally provide a data value to sign. * Returns an [`EpochKeyLiteProof`](https://developer.unirep.io/docs/circuits-api/classes/src.EpochKeyLiteProof.md). * * This proof **will not include a merkle tree proof** which makes the proof size smaller than an [`EpochKeyProof`](https://developer.unirep.io/docs/circuits-api/classes/src.EpochKeyProof.md). * It can be used to prove a seen and valid epoch key. * @param options.nonce The specified epoch key nonce. Default: `0`. * @param options.epoch The specified epoch. Default: current epoch. * @param options.data Indicates if user wants to endorse a 253-bits data. Default: `0`. * @param options.revealNonce Indicates if user wants to reveal epoch key nonce. Default: `false`. * @param options.attesterId Indicates for which attester the proof will be used. Default: `this.attesterId` * @returns The epoch key lite proof of type `EpochKeyLiteProof`. * @example * ```ts * const { publicSignals, proof } = await userState.genEpochKeyLiteProof({ * nonce: 1 * }) * ``` */ genEpochKeyLiteProof: (options?: { nonce?: number; epoch?: number; data?: bigint; revealNonce?: boolean; attesterId?: bigint | string; }) => Promise<EpochKeyLiteProof>; } export { UserState };