mirror of
https://github.com/logos-messaging/js-rln.git
synced 2026-01-02 13:43:06 +00:00
feat: add option to use service for merkle proof in generateRLNProof
This commit is contained in:
parent
10d463a512
commit
6b20df5257
122
package-lock.json
generated
122
package-lock.json
generated
@ -10,6 +10,8 @@
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"dependencies": {
|
||||
"@chainsafe/bls-keystore": "^3.0.0",
|
||||
"@noble/curves": "^1.4.0",
|
||||
"@noble/hashes": "^1.4.0",
|
||||
"@waku/core": "^0.0.25",
|
||||
"@waku/utils": "^0.0.13",
|
||||
"@waku/zerokit-rln-wasm": "^0.0.13",
|
||||
@ -1980,11 +1982,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@noble/curves": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz",
|
||||
"integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.3"
|
||||
"@noble/hashes": "1.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
@ -2002,9 +2004,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
|
||||
"integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
@ -2179,6 +2181,28 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@scure/bip32/node_modules/@noble/curves": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@scure/bip32/node_modules/@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@scure/bip39": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz",
|
||||
@ -2191,6 +2215,17 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@scure/bip39/node_modules/@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@sitespeed.io/tracium": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@sitespeed.io/tracium/-/tracium-0.3.3.tgz",
|
||||
@ -5642,6 +5677,28 @@
|
||||
"@scure/bip39": "1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ethereum-cryptography/node_modules/@noble/curves": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.3.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/ethereum-cryptography/node_modules/@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/ethers": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
|
||||
@ -13837,11 +13894,11 @@
|
||||
}
|
||||
},
|
||||
"@noble/curves": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz",
|
||||
"integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==",
|
||||
"requires": {
|
||||
"@noble/hashes": "1.3.3"
|
||||
"@noble/hashes": "1.4.0"
|
||||
}
|
||||
},
|
||||
"@noble/ed25519": {
|
||||
@ -13850,9 +13907,9 @@
|
||||
"integrity": "sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ=="
|
||||
},
|
||||
"@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA=="
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
|
||||
"integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="
|
||||
},
|
||||
"@noble/secp256k1": {
|
||||
"version": "1.7.1",
|
||||
@ -13968,6 +14025,21 @@
|
||||
"@noble/curves": "~1.3.0",
|
||||
"@noble/hashes": "~1.3.2",
|
||||
"@scure/base": "~1.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/curves": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||
"requires": {
|
||||
"@noble/hashes": "1.3.3"
|
||||
}
|
||||
},
|
||||
"@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@scure/bip39": {
|
||||
@ -13977,6 +14049,13 @@
|
||||
"requires": {
|
||||
"@noble/hashes": "~1.3.2",
|
||||
"@scure/base": "~1.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sitespeed.io/tracium": {
|
||||
@ -16609,6 +16688,21 @@
|
||||
"@noble/hashes": "1.3.3",
|
||||
"@scure/bip32": "1.3.3",
|
||||
"@scure/bip39": "1.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/curves": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||
"requires": {
|
||||
"@noble/hashes": "1.3.3"
|
||||
}
|
||||
},
|
||||
"@noble/hashes": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ethers": {
|
||||
|
||||
@ -134,6 +134,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@chainsafe/bls-keystore": "^3.0.0",
|
||||
"@noble/curves": "^1.4.0",
|
||||
"@noble/hashes": "^1.4.0",
|
||||
"@waku/core": "^0.0.25",
|
||||
"@waku/utils": "^0.0.13",
|
||||
"@waku/zerokit-rln-wasm": "^0.0.13",
|
||||
@ -143,4 +145,4 @@
|
||||
"lodash": "^4.17.21",
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +54,8 @@ describe("RLN codec with version 0", () => {
|
||||
encoder: createEncoder({ contentTopic: TestContentTopic }),
|
||||
rlnInstance,
|
||||
index,
|
||||
credential
|
||||
credential,
|
||||
fetchMembersFromService: false
|
||||
});
|
||||
const rlnDecoder = createRLNDecoder({
|
||||
rlnInstance,
|
||||
@ -384,7 +385,8 @@ describe("RLN codec with version 0 and meta setter", () => {
|
||||
encoder: createEncoder({ contentTopic: TestContentTopic, metaSetter }),
|
||||
rlnInstance,
|
||||
index,
|
||||
credential
|
||||
credential,
|
||||
fetchMembersFromService: false
|
||||
});
|
||||
const rlnDecoder = createRLNDecoder({
|
||||
rlnInstance,
|
||||
|
||||
13
src/codec.ts
13
src/codec.ts
@ -16,15 +16,18 @@ const log = debug("waku:rln:encoder");
|
||||
|
||||
export class RLNEncoder implements IEncoder {
|
||||
private readonly idSecretHash: Uint8Array;
|
||||
private readonly idCommitment: bigint;
|
||||
|
||||
constructor(
|
||||
private encoder: IEncoder,
|
||||
private rlnInstance: RLNInstance,
|
||||
private index: number,
|
||||
identityCredential: IdentityCredential
|
||||
identityCredential: IdentityCredential,
|
||||
private readonly fetchMembersFromService: boolean = false
|
||||
) {
|
||||
if (index < 0) throw "invalid membership index";
|
||||
this.idSecretHash = identityCredential.IDSecretHash;
|
||||
this.idCommitment = identityCredential.IDCommitmentBigInt;
|
||||
}
|
||||
|
||||
async toWire(message: IMessage): Promise<Uint8Array | undefined> {
|
||||
@ -49,7 +52,9 @@ export class RLNEncoder implements IEncoder {
|
||||
signal,
|
||||
this.index,
|
||||
message.timestamp,
|
||||
this.idSecretHash
|
||||
this.idSecretHash,
|
||||
this.idCommitment,
|
||||
this.fetchMembersFromService
|
||||
);
|
||||
return proof;
|
||||
}
|
||||
@ -72,6 +77,7 @@ type RLNEncoderOptions = {
|
||||
rlnInstance: RLNInstance;
|
||||
index: number;
|
||||
credential: IdentityCredential;
|
||||
fetchMembersFromService: boolean;
|
||||
};
|
||||
|
||||
export const createRLNEncoder = (options: RLNEncoderOptions): RLNEncoder => {
|
||||
@ -79,7 +85,8 @@ export const createRLNEncoder = (options: RLNEncoderOptions): RLNEncoder => {
|
||||
options.encoder,
|
||||
options.rlnInstance,
|
||||
options.index,
|
||||
options.credential
|
||||
options.credential,
|
||||
options.fetchMembersFromService
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -19,7 +19,8 @@ describe("RLN Contract abstraction", () => {
|
||||
const voidSigner = new ethers.VoidSigner(SEPOLIA_CONTRACT.address);
|
||||
const rlnContract = new RLNContract(rlnInstance, {
|
||||
registryAddress: SEPOLIA_CONTRACT.address,
|
||||
signer: voidSigner
|
||||
signer: voidSigner,
|
||||
fetchMembersFromService: false
|
||||
});
|
||||
|
||||
rlnContract["storageContract"] = {
|
||||
@ -43,7 +44,8 @@ describe("RLN Contract abstraction", () => {
|
||||
const voidSigner = new ethers.VoidSigner(SEPOLIA_CONTRACT.address);
|
||||
const rlnContract = new RLNContract(rlnInstance, {
|
||||
registryAddress: SEPOLIA_CONTRACT.address,
|
||||
signer: voidSigner
|
||||
signer: voidSigner,
|
||||
fetchMembersFromService: false
|
||||
});
|
||||
|
||||
rlnContract["storageIndex"] = 1;
|
||||
|
||||
@ -22,6 +22,7 @@ type Signer = ethers.Signer;
|
||||
type RLNContractOptions = {
|
||||
signer: Signer;
|
||||
registryAddress: string;
|
||||
fetchMembersFromService: boolean;
|
||||
};
|
||||
|
||||
type RLNStorageOptions = {
|
||||
@ -54,7 +55,9 @@ export class RLNContract {
|
||||
const rlnContract = new RLNContract(rlnInstance, options);
|
||||
|
||||
await rlnContract.initStorageContract(options.signer);
|
||||
await rlnContract.fetchMembers(rlnInstance);
|
||||
if (!options.fetchMembersFromService) {
|
||||
await rlnContract.fetchMembers(rlnInstance);
|
||||
}
|
||||
rlnContract.subscribeToMembers(rlnInstance);
|
||||
|
||||
return rlnContract;
|
||||
@ -80,8 +83,9 @@ export class RLNContract {
|
||||
): Promise<void> {
|
||||
const storageIndex = options?.storageIndex
|
||||
? options.storageIndex
|
||||
: await this.registryContract.usingStorageIndex();
|
||||
const storageAddress = await this.registryContract.storages(storageIndex);
|
||||
: await this.registryContract.callStatic.usingStorageIndex();
|
||||
const storageAddress =
|
||||
await this.registryContract.callStatic.storages(storageIndex);
|
||||
|
||||
if (!storageAddress || storageAddress === ethers.constants.AddressZero) {
|
||||
throw Error("No RLN Storage initialized on registry contract.");
|
||||
@ -95,7 +99,8 @@ export class RLNContract {
|
||||
);
|
||||
this._membersFilter = this.storageContract.filters.MemberRegistered();
|
||||
|
||||
this.deployBlock = await this.storageContract.deployedBlockNumber();
|
||||
this.deployBlock =
|
||||
await this.storageContract.callStatic.deployedBlockNumber();
|
||||
}
|
||||
|
||||
public get registry(): ethers.Contract {
|
||||
|
||||
@ -76,6 +76,7 @@ type StartRLNOptions = {
|
||||
* If provided used for validating the network chainId and connecting to registry contract.
|
||||
*/
|
||||
credentials?: EncryptedCredentials | DecryptedCredentials;
|
||||
fetchMembersFromService?: boolean;
|
||||
};
|
||||
|
||||
type RegisterMembershipOptions =
|
||||
@ -84,6 +85,7 @@ type RegisterMembershipOptions =
|
||||
|
||||
type WakuRLNEncoderOptions = WakuEncoderOptions & {
|
||||
credentials: EncryptedCredentials | DecryptedCredentials;
|
||||
fetchMembersFromService: boolean;
|
||||
};
|
||||
|
||||
export class RLNInstance {
|
||||
@ -129,7 +131,8 @@ export class RLNInstance {
|
||||
this._signer = signer!;
|
||||
this._contract = await RLNContract.init(this, {
|
||||
registryAddress: registryAddress!,
|
||||
signer: signer!
|
||||
signer: signer!,
|
||||
fetchMembersFromService: options.fetchMembersFromService ?? false
|
||||
});
|
||||
this.started = true;
|
||||
} finally {
|
||||
@ -244,7 +247,8 @@ export class RLNInstance {
|
||||
encoder: createEncoder(options),
|
||||
rlnInstance: this,
|
||||
index: credentials.membership.treeIndex,
|
||||
credential: credentials.identity
|
||||
credential: credentials.identity,
|
||||
fetchMembersFromService: options.fetchMembersFromService
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
import * as mod from "@noble/curves/abstract/modular";
|
||||
import { bytesToNumberLE, numberToBytesLE } from "@noble/curves/abstract/utils";
|
||||
import { bn254 } from "@noble/curves/bn254";
|
||||
import { keccak_256 } from "@noble/hashes/sha3";
|
||||
import * as zerokitRLN from "@waku/zerokit-rln-wasm";
|
||||
|
||||
import { concatenate, writeUIntLE } from "./bytes.js";
|
||||
@ -13,3 +17,16 @@ export function sha256(input: Uint8Array): Uint8Array {
|
||||
const lenPrefixedData = concatenate(inputLen, input);
|
||||
return zerokitRLN.hash(lenPrefixedData);
|
||||
}
|
||||
|
||||
export function hashToBN254(data: Uint8Array): Uint8Array {
|
||||
// Hash the data using Keccak256
|
||||
const hashed = keccak_256(data);
|
||||
|
||||
// Convert hash to a field element (big integer modulo BN254 field order)
|
||||
const fieldElement = mod.mod(bytesToNumberLE(hashed), bn254.CURVE.Fp.ORDER);
|
||||
|
||||
// Convert the field element back to bytes, ensuring 32 bytes length
|
||||
const fixedLenBytes = numberToBytesLE(fieldElement, 32);
|
||||
|
||||
return fixedLenBytes;
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { concatBytes, hexToBytes } from "@noble/curves/abstract/utils";
|
||||
import type { IRateLimitProof } from "@waku/interfaces";
|
||||
import * as zerokitRLN from "@waku/zerokit-rln-wasm";
|
||||
|
||||
import { IdentityCredential } from "./identity.js";
|
||||
import { Proof, proofToBytes } from "./proof.js";
|
||||
import { WitnessCalculator } from "./resources/witness_calculator.js";
|
||||
import { hashToBN254 } from "./utils/hash.js";
|
||||
import {
|
||||
concatenate,
|
||||
dateToEpoch,
|
||||
@ -78,7 +80,9 @@ export class Zerokit {
|
||||
msg: Uint8Array,
|
||||
index: number,
|
||||
epoch: Uint8Array | Date | undefined,
|
||||
idSecretHash: Uint8Array
|
||||
idSecretHash: Uint8Array,
|
||||
idCommitment?: bigint,
|
||||
fetchMembersFromService: boolean = false
|
||||
): Promise<IRateLimitProof> {
|
||||
if (epoch == undefined) {
|
||||
epoch = epochIntToBytes(dateToEpoch(new Date()));
|
||||
@ -96,10 +100,61 @@ export class Zerokit {
|
||||
epoch,
|
||||
idSecretHash
|
||||
);
|
||||
const rlnWitness = zerokitRLN.getSerializedRLNWitness(
|
||||
this.zkRLN,
|
||||
serialized_msg
|
||||
);
|
||||
|
||||
let rlnWitness;
|
||||
if (!fetchMembersFromService) {
|
||||
// Assumes merkle tree is maintained locally
|
||||
rlnWitness = zerokitRLN.getSerializedRLNWitness(
|
||||
this.zkRLN,
|
||||
serialized_msg
|
||||
);
|
||||
} else {
|
||||
// Fetch merkle data from a service provider
|
||||
if (!idCommitment) {
|
||||
throw new Error(
|
||||
"Must provide ID commitment if using service to get proof"
|
||||
);
|
||||
}
|
||||
const RLN_IDENTIFIER: Uint8Array = new TextEncoder().encode(
|
||||
"zerokit/rln/010203040506070809"
|
||||
);
|
||||
|
||||
const fetchUrl = `${process.env.MERKLE_PROOF_SERVICE_URL || "http://localhost:8645/debug/v1/merkleProof"}/${idCommitment}`;
|
||||
const response = await fetch(fetchUrl);
|
||||
|
||||
const proofData = await response.json();
|
||||
const pathElements: Uint8Array[] = proofData.pathElements.map(hexToBytes);
|
||||
|
||||
// Serialize number of path lements and each hash in path elements to a single Uint8Array
|
||||
const pathElementsBytes = new Uint8Array(8 + pathElements.length * 32);
|
||||
writeUIntLE(pathElementsBytes, pathElements.length, 0, 8);
|
||||
for (let i = 0; i < pathElements.length; i++) {
|
||||
pathElementsBytes.set(pathElements[i], 8 + i * 32);
|
||||
}
|
||||
// Serialize number of path indexes and the indexes themselves to a single Uint8Array
|
||||
const pathIndexesBytes = new Uint8Array(8 + proofData.pathIndexes.length);
|
||||
writeUIntLE(pathIndexesBytes, proofData.pathIndexes.length, 0, 8);
|
||||
for (let i = 0; i < proofData.pathIndexes.length; i++) {
|
||||
writeUIntLE(
|
||||
pathIndexesBytes,
|
||||
parseInt(proofData.pathIndexes[i], 10),
|
||||
8 + i,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
const hashToFieldMsg = hashToBN254(serialized_msg);
|
||||
const hashToFieldRLNIdentifier = hashToBN254(RLN_IDENTIFIER);
|
||||
// Append all Uint8Array elements to a single Uint8Array
|
||||
rlnWitness = concatBytes(
|
||||
idSecretHash,
|
||||
pathElementsBytes,
|
||||
pathIndexesBytes,
|
||||
hashToFieldMsg,
|
||||
epoch,
|
||||
hashToFieldRLNIdentifier
|
||||
);
|
||||
}
|
||||
const inputs = zerokitRLN.RLNWitnessToJson(this.zkRLN, rlnWitness);
|
||||
const calculatedWitness = await this.witnessCalculator.calculateWitness(
|
||||
inputs,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user