Merge pull request #12 from appliedzkp/fix/rln_revert

Fix/rln revert
This commit is contained in:
Omar Desogus
2022-01-20 11:27:10 +01:00
committed by GitHub
8 changed files with 237 additions and 118 deletions

View File

@@ -30,7 +30,7 @@ export default class ZkIdentity {
this._identityTrapdoor = identityTrapdoor
this._identityNullifier = identityNullifier
this._secret = [this._identityNullifier, this._identityTrapdoor]
this._genMultipartSecret()
this.genMultipartSecret()
break
}
@@ -40,7 +40,7 @@ export default class ZkIdentity {
this._identityTrapdoor = identityTrapdoor
this._identityNullifier = identityNullifier
this._secret = [this._identityNullifier, this._identityTrapdoor]
this._genMultipartSecret()
this.genMultipartSecret()
break
}
@@ -72,7 +72,7 @@ export default class ZkIdentity {
* @param parts The number of parts that the secret should be composed of,
* corresponding to the spam threshold of the protocol
*/
private _genMultipartSecret(parts = 2): void {
public genMultipartSecret(parts = 2): void {
if (parts < 2) throw new Error("Invalid number of parts")
const initialComponent = Fq.pow(this._identityTrapdoor, this._identityNullifier)

View File

@@ -746,11 +746,6 @@ crypto-browserify@3.12.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
crypto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
d@1, d@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"

View File

@@ -1,6 +1,7 @@
import { FullProof, Identity, MerkleProof } from "@zk-kit/types"
import RLN from "./rln"
import NRLN from "./nrln"
import Semaphore from "./semaphore"
import { generateMerkleProof, genExternalNullifier, genSignalHash } from "./utils"
export { Semaphore, RLN, generateMerkleProof, genExternalNullifier, genSignalHash, Identity, MerkleProof, FullProof }
export { Semaphore, RLN, NRLN, generateMerkleProof, genExternalNullifier, genSignalHash, Identity, MerkleProof, FullProof }

View File

@@ -0,0 +1,110 @@
import { MerkleProof } from "@zk-kit/types"
import { Fq, genSignalHash, poseidonHash } from "./utils"
import ZkProtocol from "./zk-protocol"
class NRLN extends ZkProtocol {
/**
* Creates witness for RLN proof
* @param identitySecret identity secret
* @param merkleProof merkle proof that identity exists in RLN tree
* @param epoch epoch on which signal is broadcasted
* @param signal signal that is being broadcasted
* @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering
* @param shouldHash should signal be hashed before broadcast
* @returns rln witness
*/
genWitness(
identitySecret: Array<bigint>,
merkleProof: MerkleProof,
epoch: string | bigint,
signal: string,
rlnIdentifier: bigint,
shouldHash = true
): any {
return {
identity_secret: identitySecret,
path_elements: merkleProof.siblings,
identity_path_index: merkleProof.pathIndices,
x: shouldHash ? genSignalHash(signal) : signal,
epoch,
rln_identifier: rlnIdentifier
}
}
/**
*
* @param identitySecret identity secret
* @param epoch epoch
* @param x singal hash
* @param limit number of messages per epoch allowed
* @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering
* @returns
*/
calculateOutput(
identitySecret: Array<bigint>,
epoch: bigint,
x: bigint,
limit: number,
rlnIdentifier: bigint
): Array<bigint> {
const a0 = poseidonHash(identitySecret)
const coeffs: Array<bigint> = []
let tmpX = x
coeffs.push(poseidonHash([identitySecret[0], epoch]))
let y: bigint = Fq.add(Fq.mul(coeffs[0], tmpX), a0)
for (let i = 1; i < limit; i += 1) {
tmpX = Fq.mul(x, tmpX)
coeffs.push(poseidonHash([identitySecret[i], epoch]))
y = Fq.add(y, Fq.mul(coeffs[i], tmpX))
}
coeffs.push(poseidonHash([rlnIdentifier]))
const nullifier: bigint = this.genNullifier(coeffs)
return [y, nullifier]
}
/**
* Calculates slashing nullifier
* @param coeffs coeefitients from calculated polinomial
* @returns slashing nullifier
*/
genNullifier(coeffs: Array<bigint>): bigint {
return poseidonHash(coeffs)
}
/**
* When spam occurs, identity secret can be retrieved
* @param xs
* @param ys
* @returns identity secret
*/
retrieveSecret(xs: Array<bigint>, ys: Array<bigint>): bigint {
if (xs.length !== ys.length) throw new Error("x and y arrays must be of same size")
const numOfPoints: number = xs.length
let f0 = BigInt(0)
for (let i = 0; i < numOfPoints; i += 1) {
let p = BigInt(1)
for (let j = 0; j < numOfPoints; j += 1) {
if (j !== i) {
p = Fq.mul(p, Fq.div(xs[j], Fq.sub(xs[j], xs[i])))
}
}
f0 = Fq.add(f0, Fq.mul(ys[i], p))
}
return f0
}
/**
*
* @returns unique identifier of the rln dapp
*/
genIdentifier(): bigint {
return Fq.random()
}
}
export default new NRLN()

View File

@@ -4,7 +4,7 @@ import ZkProtocol from "./zk-protocol"
class RLN extends ZkProtocol {
/**
* Creates witness for RLN proof
* Creates witness for rln proof
* @param identitySecret identity secret
* @param merkleProof merkle proof that identity exists in RLN tree
* @param epoch epoch on which signal is broadcasted
@@ -14,7 +14,7 @@ class RLN extends ZkProtocol {
* @returns rln witness
*/
genWitness(
identitySecret: Array<bigint>,
identitySecret: bigint,
merkleProof: MerkleProof,
epoch: string | bigint,
signal: string,
@@ -32,70 +32,42 @@ class RLN extends ZkProtocol {
}
/**
*
* Calculates
* @param identitySecret identity secret
* @param epoch epoch
* @param x singal hash
* @param limit number of messages per epoch allowed
* @param rlnIdentifier identifier used by each separate app, needed for more accurate spam filtering
* @returns
* @param epoch epoch on which signal is broadcasted
* @param rlnIdentifier unique identifier of rln dapp
* @param x signal hash
* @returns y & slashing nullfier
*/
calculateOutput(
identitySecret: Array<bigint>,
epoch: bigint,
x: bigint,
limit: number,
rlnIdentifier: bigint
): Array<bigint> {
const a0 = poseidonHash(identitySecret)
const coeffs: Array<bigint> = []
let tmpX = x
coeffs.push(poseidonHash([identitySecret[0], epoch]))
let y: bigint = Fq.add(Fq.mul(coeffs[0], tmpX), a0)
for (let i = 1; i < limit; i += 1) {
tmpX = Fq.mul(x, tmpX)
coeffs.push(poseidonHash([identitySecret[i], epoch]))
y = Fq.add(y, Fq.mul(coeffs[i], tmpX))
}
coeffs.push(poseidonHash([rlnIdentifier]))
const nullifier: bigint = this.genNullifier(coeffs)
calculateOutput(identitySecret: bigint, epoch: bigint, rlnIdentifier: bigint, x: bigint): Array<bigint> {
const a1: bigint = poseidonHash([identitySecret, epoch])
const y: bigint = Fq.normalize(a1 * x + identitySecret)
const nullifier = this.genNullifier(a1, rlnIdentifier)
return [y, nullifier]
}
/**
* Calculates slashing nullifier
* @param coeffs coeefitients from calculated polinomial
* @returns slashing nullifier
*
* @param a1 y = a1 * x + a0 (a1 = poseidonHash(identity secret, epoch, rlnIdentifier))
* @param rlnIdentifier unique identifier of rln dapp
* @returns rln slashing nullifier
*/
genNullifier(coeffs: Array<bigint>): bigint {
return poseidonHash(coeffs)
genNullifier(a1: bigint, rlnIdentifier: bigint): bigint {
return poseidonHash([a1, rlnIdentifier])
}
/**
* When spam occurs, identity secret can be retrieved
* @param xs
* @param ys
* @param x1 x1
* @param x2 x2
* @param y1 y1
* @param y2 y2
* @returns identity secret
*/
retrieveSecret(xs: Array<bigint>, ys: Array<bigint>): bigint {
if (xs.length !== ys.length) throw new Error("x and y arrays must be of same size")
const numOfPoints: number = xs.length
let f0 = BigInt(0)
for (let i = 0; i < numOfPoints; i += 1) {
let p = BigInt(1)
for (let j = 0; j < numOfPoints; j += 1) {
if (j !== i) {
p = Fq.mul(p, Fq.div(xs[j], Fq.sub(xs[j], xs[i])))
}
}
f0 = Fq.add(f0, Fq.mul(ys[i], p))
}
return f0
retrieveSecret(x1: bigint, x2: bigint, y1: bigint, y2: bigint): bigint {
const slope = Fq.div(Fq.sub(y2, y1), Fq.sub(x2, x1))
const privateKey = Fq.sub(y1, Fq.mul(slope, x1))
return Fq.normalize(privateKey)
}
/**
@@ -107,4 +79,4 @@ class RLN extends ZkProtocol {
}
}
export default new RLN()
export default new RLN()

View File

@@ -2,7 +2,7 @@ import { FullProof, MerkleProof } from "@zk-kit/types"
import * as fs from "fs"
import * as path from "path"
import { SecretType, ZkIdentity } from "@zk-kit/identity"
import { RLN } from "../src"
import { NRLN } from "../src"
import { generateMerkleProof, genExternalNullifier, genSignalHash, poseidonHash } from "../src/utils"
const identityCommitments: Array<bigint> = []
@@ -19,9 +19,9 @@ beforeAll(() => {
}
})
describe("RLN with non default spam threshold", () => {
describe("RLN features", () => {
it("Generate RLN witness", () => {
describe("NRLN", () => {
describe("NRLN features", () => {
it("Generate NRLN witness", () => {
const identity: ZkIdentity = new ZkIdentity()
identity.genMultipartSecret(SPAM_TRESHOLD)
@@ -33,14 +33,14 @@ describe("RLN with non default spam threshold", () => {
const signal = "hey hey"
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
const rlnIdentifier: bigint = NRLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = RLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
const witness: FullProof = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
expect(typeof witness).toBe("object")
})
it.skip("Generate RLN proof and verify it", async () => {
it.skip("Generate NRLN proof and verify it", async () => {
/**
* Compiled RLN circuits are needed to run this test so it's being skipped in hooks
*/
@@ -56,12 +56,12 @@ describe("RLN with non default spam threshold", () => {
const signal = "hey hey"
const signalHash = genSignalHash(signal)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
const rlnIdentifier: bigint = NRLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = RLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
const witness: FullProof = NRLN.genWitness(identitySecret, merkleProof, epoch, signal, rlnIdentifier)
const [y, nullifier] = RLN.calculateOutput(
const [y, nullifier] = NRLN.calculateOutput(
identitySecret,
BigInt(epoch),
signalHash,
@@ -70,14 +70,14 @@ describe("RLN with non default spam threshold", () => {
)
const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier]
const vkeyPath: string = path.join("./zkeyFiles", "rln_3", "verification_key.json")
const vkeyPath: string = path.join("./zkeyFiles", "nrln", "verification_key.json")
const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8"))
const wasmFilePath: string = path.join("./zkeyFiles", "rln_3", "rln.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "rln_3", "rln_final.zkey")
const wasmFilePath: string = path.join("./zkeyFiles", "nrln", "rln.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "nrln", "rln_final.zkey")
const fullProof: FullProof = await RLN.genProof(witness, wasmFilePath, finalZkeyPath)
const res: boolean = await RLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
const fullProof: FullProof = await NRLN.genProof(witness, wasmFilePath, finalZkeyPath)
const res: boolean = await NRLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
expect(res).toBe(true)
}, 30000)
@@ -97,14 +97,14 @@ describe("RLN with non default spam threshold", () => {
const signalHash4 = genSignalHash(signal4)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
const rlnIdentifier: bigint = NRLN.genIdentifier()
const [y1] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash1, SPAM_TRESHOLD, rlnIdentifier)
const [y2] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash2, SPAM_TRESHOLD, rlnIdentifier)
const [y3] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash3, SPAM_TRESHOLD, rlnIdentifier)
const [y4] = RLN.calculateOutput(identitySecret, BigInt(epoch), signalHash4, SPAM_TRESHOLD, rlnIdentifier)
const [y1] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash1, SPAM_TRESHOLD, rlnIdentifier)
const [y2] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash2, SPAM_TRESHOLD, rlnIdentifier)
const [y3] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash3, SPAM_TRESHOLD, rlnIdentifier)
const [y4] = NRLN.calculateOutput(identitySecret, BigInt(epoch), signalHash4, SPAM_TRESHOLD, rlnIdentifier)
const retrievedSecret: bigint = RLN.retrieveSecret(
const retrievedSecret: bigint = NRLN.retrieveSecret(
[signalHash1, signalHash2, signalHash3, signalHash4],
[y1, y2, y3, y4]
)

View File

@@ -17,12 +17,12 @@ beforeAll(() => {
}
})
describe("RLN with default spam threshold", () => {
describe("RLN tests", () => {
describe("RLN functionalities", () => {
it("Generate RLN witness", () => {
const identity: ZkIdentity = new ZkIdentity()
const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET)
const secret: bigint[] = identity.getMultipartSecret()
it("Generate rln witness", () => {
const identity: ZkIdentity = new ZkIdentity();
const identityCommitment: bigint = identity.genIdentityCommitment();
const secretHash: bigint = identity.getMultipartSecretHash();
const commitments: Array<bigint> = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
@@ -32,19 +32,18 @@ describe("RLN with default spam threshold", () => {
const rlnIdentifier: bigint = RLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = RLN.genWitness(secret, merkleProof, epoch, signal, rlnIdentifier)
const witness: FullProof = RLN.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier)
expect(typeof witness).toBe("object")
})
it.skip("Generate RLN proof and verify it", async () => {
it.skip("Generate rln proof and verify it", async () => {
/**
* Compiled RLN circuits are needed to run this test so it's being skipped in hooks
*/
const identity: ZkIdentity = new ZkIdentity()
identity.genMultipartSecret(2)
const secret: bigint[] = identity.getMultipartSecret()
console.log("multipart secret", secret)
const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET)
const identity: ZkIdentity = new ZkIdentity();
const secretHash: bigint = identity.getMultipartSecretHash()
const identityCommitment: bigint = identity.genIdentityCommitment(SecretType.MULTIPART_SECRET);
const commitments: Array<bigint> = Object.assign([], identityCommitments)
commitments.push(identityCommitment)
@@ -55,41 +54,40 @@ describe("RLN with default spam threshold", () => {
const rlnIdentifier: bigint = RLN.genIdentifier()
const merkleProof: MerkleProof = generateMerkleProof(15, BigInt(0), 2, commitments, identityCommitment)
const witness: FullProof = RLN.genWitness(secret, merkleProof, epoch, signal, rlnIdentifier)
const witness: FullProof = RLN.genWitness(secretHash, merkleProof, epoch, signal, rlnIdentifier)
const [y, nullifier] = RLN.calculateOutput(secret, BigInt(epoch), signalHash, 2, rlnIdentifier)
const [y, nullifier] = RLN.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash)
const publicSignals = [y, merkleProof.root, nullifier, signalHash, epoch, rlnIdentifier]
const vkeyPath: string = path.join("./zkeyFiles", "rln_default", "verification_key.json")
const vkeyPath: string = path.join("./zkeyFiles", "rln", "verification_key.json")
const vKey = JSON.parse(fs.readFileSync(vkeyPath, "utf-8"))
const wasmFilePath: string = path.join("./zkeyFiles", "rln_default", "rln.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "rln_default", "rln_final.zkey")
const wasmFilePath: string = path.join("./zkeyFiles", "rln", "rln.wasm")
const finalZkeyPath: string = path.join("./zkeyFiles", "rln", "rln_final.zkey")
const fullProof: FullProof = await RLN.genProof(witness, wasmFilePath, finalZkeyPath)
const res: boolean = await RLN.verifyProof(vKey, { proof: fullProof.proof, publicSignals })
expect(res).toBe(true)
}, 30000)
it("Should retrieve user secret after spaming", () => {
const identity: ZkIdentity = new ZkIdentity();
const secretHash: bigint = identity.getSecretHash()
// it("Should retrieve user secret after spaming", () => {
// const identity: ZkIdentity = new ZkIdentity();
// const secret: bigint[] = identity.getMultipartSecret();
const signal1 = "hey hey"
const signalHash1 = genSignalHash(signal1)
const signal2 = "hey hey again"
const signalHash2 = genSignalHash(signal2)
// const signal1 = "hey hey"
// const signalHash1 = genSignalHash(signal1)
// const signal2 = "hey hey again"
// const signalHash2 = genSignalHash(signal2)
const epoch: string = genExternalNullifier("test-epoch")
const rlnIdentifier: bigint = RLN.genIdentifier()
// const epoch: string = genExternalNullifier("test-epoch")
// const rlnIdentifier: bigint = RLN.genIdentifier()
const [y1] = RLN.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash1)
const [y2] = RLN.calculateOutput(secretHash, BigInt(epoch), rlnIdentifier, signalHash2)
// const [y1] = RLN.calculateOutput(secret, BigInt(epoch), signalHash1, 2, rlnIdentifier )
// const [y2] = RLN.calculateOutput(secret, BigInt(epoch), signalHash2, 2, rlnIdentifier)
const retrievedSecret: bigint = RLN.retrieveSecret(signalHash1, signalHash2, y1, y2)
// const retrievedSecret: bigint = RLN.retrieveSecret([signalHash1, signalHash2], [y1, y2])
// expect(retrievedSecret).toEqual(secret)
// })
expect(retrievedSecret).toEqual(secretHash)
})
})
})
})

View File

@@ -919,6 +919,11 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
"@juanelas/base64@^1.0.1":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@juanelas/base64/-/base64-1.0.4.tgz#e457b9e8e10170f3d2ad685b7a82655bc4397c8b"
integrity sha512-KUidDSb+K7Rkoy2uJ/HdCnt4soNRlhNXONU8r8Cgic6Qq3E9BPg4kMSYXchM37WpYvGEGq2NUq/kCegMSLhtIg==
"@nomiclabs/hardhat-ethers@^2.0.2":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.4.tgz#288889c338acaf47cabd29020e561d0077b7efcf"
@@ -1223,6 +1228,27 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@zk-kit/identity@^1.0.22":
version "1.0.22"
resolved "https://registry.yarnpkg.com/@zk-kit/identity/-/identity-1.0.22.tgz#190278c5e5fbe8cf524ca6f1f07f38db5f1ad813"
integrity sha512-YACEBGO7T0K3wPZcouwpKgwqFPvweYYdPGjKJ+Svr/Nx+hwufnC9n5u/hnH5AT+c561dmqj3bNyx+Wt4VWyfrw==
dependencies:
"@zk-kit/types" "^1.0.9"
bigint-conversion "^2.1.12"
circomlibjs "^0.0.8"
crypto "^1.0.1"
js-sha256 "^0.9.0"
"@zk-kit/incremental-merkle-tree@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@zk-kit/incremental-merkle-tree/-/incremental-merkle-tree-0.2.0.tgz#ce0f801ded56d6ca7baf8400a5a5d14c15f744bf"
integrity sha512-9QTZ44cIMFJhr18IV9TMZrNcl69gbCAqIK87pl5Ni+2hZum5ikc0qFdMScLKyYFjEECJeVBZrZr2I9AjzXJh4w==
"@zk-kit/types@^1.0.9":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@zk-kit/types/-/types-1.0.9.tgz#550883c880e1da5421bc3f2f1d058c724b304aa3"
integrity sha512-Ve7anjIWaBDCM5wrreJQ0U9H4BSbDd9y6BfykPJM9ISJo6NeKnGXiSMZxJdTfVv8mT0DnOZgNarJ4a/n0fPVfw==
abab@^2.0.3, abab@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
@@ -1640,6 +1666,13 @@ big-integer@^1.6.42, big-integer@^1.6.48:
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
bigint-conversion@^2.1.12:
version "2.2.1"
resolved "https://registry.yarnpkg.com/bigint-conversion/-/bigint-conversion-2.2.1.tgz#08c9f17a826943c7e56d4bfa9f0fc7fe8050a940"
integrity sha512-9TvqpV+VZ04fPKv4KPLQRk5ZAFhgHX4F7bYQY263/BbJBFzEGbtBeTQV9oNuAGaqj88PXdov1OcSNQtq9K9MPA==
dependencies:
"@juanelas/base64" "^1.0.1"
bignumber.js@^9.0.0:
version "9.0.2"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673"
@@ -2244,7 +2277,7 @@ circomlib@^0.5.1:
ffjavascript "0.2.38"
web3-utils "^1.3.0"
circomlibjs@0.0.8:
circomlibjs@0.0.8, circomlibjs@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/circomlibjs/-/circomlibjs-0.0.8.tgz#c2d1130d2d99fbb22f3d40ac19f347d768eace76"
integrity sha512-oZFYapLO0mfiA+i2GU/V7bRNEEPjVcwV4M444nU5lNsdSJpqLwD57m9zxTD5m/KeY7WQ3lEAC9NNKEPQHu7s1w==
@@ -2562,6 +2595,11 @@ crypto-browserify@3.12.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
crypto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
cssom@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
@@ -5134,6 +5172,11 @@ js-cleanup@^1.2.0:
perf-regexes "^1.0.1"
skip-regex "^1.0.2"
js-sha256@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966"
integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==
js-sha3@0.8.0, js-sha3@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"