From 28f25e14d689f17d5b2b403db8072b15bf1853e9 Mon Sep 17 00:00:00 2001 From: Sasha Date: Tue, 11 Apr 2023 22:09:07 +0200 Subject: [PATCH 01/12] change block number --- examples/rln-js/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rln-js/index.html b/examples/rln-js/index.html index 62fd950a..4ae7cda4 100644 --- a/examples/rln-js/index.html +++ b/examples/rln-js/index.html @@ -308,7 +308,7 @@

Messages

} }; - const rlnDeployBlk = 7109391; + const rlnDeployBlk = 8813000; const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; const rlnAbi = [ "function MEMBERSHIP_DEPOSIT() public view returns(uint256)", From 1186b135b6e95fd2ed4cbd69e6f113b6dbaa40a1 Mon Sep 17 00:00:00 2001 From: Sasha Date: Wed, 12 Apr 2023 00:28:29 +0200 Subject: [PATCH 02/12] use RLNContract --- examples/rln-js/index.html | 119 +++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/examples/rln-js/index.html b/examples/rln-js/index.html index 4ae7cda4..bcd2cd2c 100644 --- a/examples/rln-js/index.html +++ b/examples/rln-js/index.html @@ -147,7 +147,8 @@

Messages

MembershipKey, RLNDecoder, RLNEncoder, - } from "https://unpkg.com/@waku/rln@0.0.13/bundle/index.js"; + RLNContract, + } from "https://unpkg.com/@waku/rln@0.0.13-fae4bea/bundle/index.js"; import { ethers } from "https://unpkg.com/ethers@5.7.2/dist/ethers.esm.min.js"; @@ -225,6 +226,28 @@

Messages

.add(new protobuf.Field("nick", 2, "string")) .add(new protobuf.Field("text", 3, "bytes")); + const rlnDeployBlk = 8813000; + const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; + const rlnAbi = [ + "function MEMBERSHIP_DEPOSIT() public view returns(uint256)", + "function register(uint256 pubkey) external payable", + "function withdraw(uint256 secret, uint256 _pubkeyIndex, address payable receiver) external", + "event MemberRegistered(uint256 pubkey, uint256 index)", + "event MemberWithdrawn(uint256 pubkey, uint256 index)", + ]; + + const provider = new ethers.providers.Web3Provider( + window.ethereum, + "any" + ); + + let accounts; + let signature; + let rlnContract = new RLNContract({ + address: rlnAddress, + provider: provider.getSigner(), + }); + // Function to update the fields to guide the user by disabling buttons. const updateFields = () => { if (membershipKey) { @@ -283,15 +306,14 @@

Messages

importFromWalletButton.onclick = async () => { const signer = provider.getSigner(); - const signature = await signer.signMessage(SIGNATURE_MESSAGE); - + signature = await signer.signMessage(SIGNATURE_MESSAGE); membershipKey = await rlnInstance.generateSeededMembershipKey( signature ); const idCommitment = ethers.utils.hexlify(membershipKey.IDCommitment); - allMemberships.forEach((m) => { + rlnContract.members.forEach((m) => { if (m.pubkey._hex === idCommitment) { membershipId = m.index.toString(); } @@ -308,40 +330,13 @@

Messages

} }; - const rlnDeployBlk = 8813000; - const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; - const rlnAbi = [ - "function MEMBERSHIP_DEPOSIT() public view returns(uint256)", - "function register(uint256 pubkey) external payable", - "function withdraw(uint256 secret, uint256 _pubkeyIndex, address payable receiver) external", - "event MemberRegistered(uint256 pubkey, uint256 index)", - "event MemberWithdrawn(uint256 pubkey, uint256 index)", - ]; - - const provider = new ethers.providers.Web3Provider( - window.ethereum, - "any" - ); - - let accounts; - let rlnContract; - - const handleMembership = (pubkey, index) => { + const updateLastMember = (pubkey, index) => { try { - allMemberships.push({ pubkey, index }); - const idCommitment = ethers.utils.zeroPad( ethers.utils.arrayify(pubkey), 32 ); - rlnInstance.insertMember(idCommitment); const indexInt = index.toNumber(); - if ( - !latestMembershipSpan.innerText || - indexInt > latestMembershipSpan.innerText - ) { - latestMembershipSpan.innerText = indexInt; - } console.debug( "IDCommitment registered in tree", idCommitment, @@ -372,24 +367,19 @@

Messages

}; retrieveRLNDetailsButton.onclick = async () => { - rlnContract = new ethers.Contract(rlnAddress, rlnAbi, provider); + const filter = rlnContract.contract.filters.MemberRegistered(); - const filter = rlnContract.filters.MemberRegistered(); - - // populating merkle tree: - const alreadyRegisteredMembers = await rlnContract.queryFilter( - filter, - rlnDeployBlk - ); - alreadyRegisteredMembers.forEach((event) => { - handleMembership(event.args.pubkey, event.args.index, event); - }); + await rlnContract.fetchMembers(rlnInstance, rlnDeployBlk); + rlnContract.subscribeToMembers(rlnInstance); retrievedRLNEvents = true; - // reacting to new registrations - rlnContract.on(filter, (pubkey, index, event) => { - handleMembership(event.args.pubkey, event.args.index, event); + const { pubkey, index } = rlnContract.members.at(-1); + updateLastMember(pubkey, index); + + // make sure we have subscriptions to keep updating last item + rlnContract.contract.on(filter, (pubkey, index, event) => { + updateLastMember(event.args.pubkey, event.args.index); }); updateFields(); }; @@ -403,30 +393,41 @@

Messages

try { registerButton.disabled = true; - const idCommitment = membershipKey.IDCommitment; - const reversedArray = idCommitment.slice().reverse(); - const pubkey = ethers.utils.hexlify(reversedArray).toString(); + let event; + + if (signature) { + event = await rlnContract.registerMember(rlnInstance, signature); + } else { + // if user imports credentials manually + // TODO: add logic to cover it in RLNContract + const idCommitment = membershipKey.IDCommitment; + const reversedArray = idCommitment.slice().reverse(); + const pubkey = ethers.utils.hexlify(reversedArray).toString(); - const price = await rlnContract.MEMBERSHIP_DEPOSIT(); + const price = await rlnContract.MEMBERSHIP_DEPOSIT(); - const signer = provider.getSigner(); - const rlnContractWithSigner = rlnContract.connect(signer); + const signer = provider.getSigner(); + const rlnContractWithSigner = rlnContract.connect(signer); - const txResponse = await rlnContractWithSigner.register(pubkey, { - value: price, - }); - console.log("Transaction broadcasted:", txResponse); + const txResponse = await rlnContractWithSigner.register(pubkey, { + value: price, + }); + console.log("Transaction broadcasted:", txResponse); - const txReceipt = await txResponse.wait(); + const txReceipt = await txResponse.wait(); - console.log("Transaction receipt", txReceipt); + console.log("Transaction receipt", txReceipt); + + event = txReceipt.events[0]; + } // Update membershipId - membershipId = txReceipt.events[0].args.index.toNumber(); + membershipId = event.args.index.toNumber(); console.log( "Obtained index for current membership credentials", membershipId ); + updateFields(); registerButton.disabled = false; } catch (err) { From 5b7310475fcc5c27525621f6292467461b64bcf3 Mon Sep 17 00:00:00 2001 From: Sasha Date: Thu, 13 Apr 2023 01:45:21 +0200 Subject: [PATCH 03/12] move to module, refactor --- examples/rln-js/index.html | 425 +------------------------------- examples/rln-js/index.js | 491 +++++++++++++++++++++++++++++++++++++ 2 files changed, 493 insertions(+), 423 deletions(-) create mode 100644 examples/rln-js/index.js diff --git a/examples/rln-js/index.html b/examples/rln-js/index.html index bcd2cd2c..f956250a 100644 --- a/examples/rln-js/index.html +++ b/examples/rln-js/index.html @@ -129,429 +129,8 @@

Waku

Messages

-
+
    - + diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js new file mode 100644 index 00000000..7c40f94f --- /dev/null +++ b/examples/rln-js/index.js @@ -0,0 +1,491 @@ +import { utils } from "https://unpkg.com/js-waku@0.30.0/bundle/index.js"; +import { createLightNode } from "https://unpkg.com/js-waku@0.30.0/bundle/lib/create_waku.js"; +import { waitForRemotePeer } from "https://unpkg.com/js-waku@0.30.0/bundle/lib/wait_for_remote_peer.js"; +import { + EncoderV0, + DecoderV0, +} from "https://unpkg.com/js-waku@0.30.0/bundle/lib/waku_message/version_0.js"; +import { protobuf } from "https://taisukef.github.io/protobuf-es.js/dist/protobuf-es.js"; +import { + create, + MembershipKey, + RLNDecoder, + RLNEncoder, + RLNContract, +} from "https://unpkg.com/@waku/rln@0.0.13-fae4bea/bundle/index.js"; +import { ethers } from "https://unpkg.com/ethers@5.7.2/dist/ethers.esm.min.js"; + +const ContentTopic = "/toy-chat/2/luzhou/proto"; + +// Protobuf +const ProtoChatMessage = new protobuf.Type("ChatMessage") + .add(new protobuf.Field("timestamp", 1, "uint64")) + .add(new protobuf.Field("nick", 2, "string")) + .add(new protobuf.Field("text", 3, "bytes")); + +const rlnDeployBlk = 8818900; +const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; + +const SIGNATURE_MESSAGE = + "The signature of this message will be used to generate your RLN credentials. Anyone accessing it may send messages on your behalf, please only share with the RLN dApp"; + +run() + .then(() => { + console.log("Successfully started application."); + }) + .catch((err) => { + console.error("Failed at starting application with ", err.message); + }); + +async function run() { + const ui = initUI(); + const rln = await initRLN(ui); + const waku = await initWaku(ui, rln); +} + +async function initRLN(ui) { + const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); + + ui.setRlnStatus("WASM Blob download in progress..."); + const rlnInstance = await create(); + ui.setRlnStatus("WASM Blob download in progress... done!"); + + const rlnContract = new RLNContract({ + address: rlnAddress, + provider: provider.getSigner(), + }); + + // Wallet logic + window.ethereum.on("accountsChanged", ui.setAccount); + window.ethereum.on("chainChanged", (chainId) => { + const id = parseInt(chainId, 16); + ui.disableIfNotGoerli(id); + }); + ui.onConnectWallet(async () => { + try { + const accounts = await provider.send("eth_requestAccounts", []); + ui.setAccount(accounts); + const network = await provider.getNetwork(); + ui.disableIfNotGoerli(network.chainId); + } catch (e) { + console.log("No web3 provider available", e); + } + }); + + ui.onRetrieveDetails(async () => { + const filter = rlnContract.contract.filters.MemberRegistered(); + + await rlnContract.fetchMembers(rlnInstance, rlnDeployBlk); + rlnContract.subscribeToMembers(rlnInstance); + + const last = rlnContract.members.at(-1); + + if (last) { + ui.setLastMember(last.index, last.pubkey); + } + + // make sure we have subscriptions to keep updating last item + rlnContract.contract.on(filter, (_pubkey, _index, event) => { + ui.setLastMember(event.args.index, event.args.pubkey); + }); + }); + + let encoder; + let signature; + let membershipId; + let membershipKey; + + ui.onManualImport((id, key) => { + membershipId = id; + membershipKey = key; + + encoder = new RLNEncoder( + new EncoderV0(ContentTopic), + rlnInstance, + membershipId, + membershipKey + ); + + ui.setMembershipInfo(membershipId, membershipKey); + ui.enableDialButton(); + }); + + ui.onWalletImport(async () => { + const signer = provider.getSigner(); + + signature = await signer.signMessage(SIGNATURE_MESSAGE); + membershipKey = await rlnInstance.generateSeededMembershipKey(signature); + + const idCommitment = ethers.utils.hexlify(membershipKey.IDCommitment); + + rlnContract.members.forEach((m) => { + if (m.pubkey._hex === idCommitment) { + membershipId = m.index.toString(); + } + }); + + if (membershipId) { + encoder = new RLNEncoder( + new EncoderV0(ContentTopic), + rlnInstance, + membershipId, + membershipKey + ); + } + + ui.setMembershipInfo(membershipId, membershipKey); + + const network = await provider.getNetwork(); + ui.enableRegisterButtonForGoerli(network.chainId); + }); + + ui.onRegister(async () => { + let event; + + ui.setRlnStatus("Trying to register..."); + if (signature) { + event = await rlnContract.registerMember(rlnInstance, signature); + } else { + // if user imports credentials manually + // TODO(@weboko): add logic to cover it in RLNContract + const idCommitment = membershipKey.IDCommitment; + const reversedArray = idCommitment.slice().reverse(); + const pubkey = ethers.utils.hexlify(reversedArray).toString(); + + const price = await rlnContract.MEMBERSHIP_DEPOSIT(); + + const signer = provider.getSigner(); + const rlnContractWithSigner = rlnContract.connect(signer); + + const txResponse = await rlnContractWithSigner.register(pubkey, { + value: price, + }); + console.log("Transaction broadcasted:", txResponse); + + const txReceipt = await txResponse.wait(); + + console.log("Transaction receipt", txReceipt); + + event = txReceipt.events[0]; + } + + // Update membershipId + membershipId = event.args.index.toNumber(); + + console.log( + "Obtained index for current membership credentials", + membershipId + ); + + ui.setRlnStatus("Successfully registered."); + ui.setMembershipInfo(membershipId, membershipKey); + ui.enableDialButton(); + }); + + return { + encoder, + rlnInstance, + }; +} + +async function initWaku(ui, rln) { + ui.setWakuStatus("Creating Waku node."); + const node = await createLightNode(); + ui.setWakuStatus("Starting Waku node."); + + await node.start(); + ui.setWakuStatus("Waku node started."); + + const verifyMessageAndRender = (message) => { + if (message.proofState === "verifying...") { + try { + console.log("Verifying proof without roots"); + console.time("proof_verify_timer"); + const res = message.verifyNoRoot(); + console.timeEnd("proof_verify_timer"); + console.log("proof verified without roots", res); + if (res === undefined) { + message.proofState = "no proof attached"; + } else if (res) { + message.proofState = "verified."; + } else { + message.proofState = "invalid!"; + } + } catch (e) { + message.proofState = "Error encountered, check console"; + console.error("Error verifying proof:", e); + } + + ui.renderMessage(message); + console.log("Verifying proof with roots", message.verify()); + } + }; + + const onFilterMessage = (wakuMessage) => { + const { timestamp, nick, text } = ProtoChatMessage.decode( + wakuMessage.payload + ); + + const time = new Date(); + time.setTime(Number(timestamp) * 1000); + + if (wakuMessage.rateLimitProof) { + console.log("Proof received:", wakuMessage.rateLimitProof); + } + + wakuMessage.proofState = !!wakuMessage.rateLimitProof + ? "verifying..." + : "no proof attached"; + + wakuMessage.msg = ` + (${nick}) + ${utils.bytesToUtf8(text)} + [${time.toISOString()}] + `; + + verifyMessageAndRender(wakuMessage); + }; + + ui.onDial(async (multiaddr) => { + ui.setWakuStatus("Dialing peer."); + + await node.dial(multiaddr, ["filter", "lightpush"]); + await waitForRemotePeer(node, ["filter", "lightpush"]); + + ui.setWakuStatus("Waku node connected."); + + const decoder = new RLNDecoder( + rln.rlnInstance, + new DecoderV0(ContentTopic) + ); + + await node.filter.subscribe([decoder], onFilterMessage); + + ui.setWakuStatus("Waku node subscribed."); + ui.enableChatButtonsIfNickSet(); + }); + + ui.onSendMessage(async (nick, text) => { + const timestamp = new Date(); + const msg = ProtoChatMessage.create({ + text, + nick, + timestamp: Math.floor(timestamp.valueOf() / 1000), + }); + const payload = ProtoChatMessage.encode(msg).finish(); + console.log("Sending message with proof..."); + + ui.setSendingStatus("sending..."); + await node.lightPush.push(rln.encoder, { payload, timestamp }); + ui.setSendingStatus("sent!"); + + console.log("Message sent!"); + ui.clearMessageArea(); + }); +} + +function initUI() { + const statusSpan = document.getElementById("status"); + + // Blockchain Elements + const addressDiv = document.getElementById("address"); + const connectWalletButton = document.getElementById("connect-wallet"); + const latestMembershipSpan = document.getElementById("latest-membership-id"); + const retrieveRLNDetailsButton = document.getElementById( + "retrieve-rln-details" + ); + + // Credentials Elements + const membershipIdInput = document.getElementById("membership-id"); + const identityKeyInput = document.getElementById("id-key"); + const commitmentKeyInput = document.getElementById("commitment-key"); + const importManually = document.getElementById("import-manually-button"); + const importFromWalletButton = document.getElementById( + "import-from-wallet-button" + ); + + const idDiv = document.getElementById("id"); + const keyDiv = document.getElementById("key"); + const commitmentDiv = document.getElementById("commitment"); + const registerButton = document.getElementById("register-button"); + + // Waku Elements + const statusDiv = document.getElementById("waku-status"); + const remoteMultiAddrInput = document.getElementById("remote-multiaddr"); + const dialButton = document.getElementById("dial"); + + const nicknameInput = document.getElementById("nick-input"); + const textInput = document.getElementById("textInput"); + const sendButton = document.getElementById("sendButton"); + const sendingStatusSpan = document.getElementById("sending-status"); + const messagesList = document.getElementById("messagesList"); + + // set initial state + idDiv.innerText = "not registered yet"; + registerButton.disabled = true; + importManually.disabled = true; + textInput.disabled = true; + sendButton.disabled = true; + dialButton.disabled = true; + retrieveRLNDetailsButton.disabled = true; + nicknameInput.disabled = true; + + // monitor & enable buttons if needed + membershipIdInput.onchange = enableManualImportIfNeeded; + identityKeyInput.onchange = enableManualImportIfNeeded; + commitmentKeyInput.onchange = enableManualImportIfNeeded; + + function enableManualImportIfNeeded() { + const isValuesPresent = + identityKeyInput.value && + commitmentKeyInput.value && + membershipIdInput.value; + + if (isValuesPresent) { + importManually.disabled = false; + } + } + + nicknameInput.onchange = enableChatIfNeeded; + nicknameInput.onblur = enableChatIfNeeded; + + function enableChatIfNeeded() { + if (nicknameInput.value) { + textInput.disabled = false; + sendButton.disabled = false; + } + } + + return { + // UI for RLN + setRlnStatus(text) { + statusSpan.innerText = text; + }, + setMembershipInfo(id, key) { + idDiv.innerText = id || "not registered yet"; + keyDiv.innerText = utils.bytesToHex(key.IDKey); + commitmentDiv.innerText = utils.bytesToHex(key.IDCommitment); + }, + setLastMember(index, pubkey) { + try { + const idCommitment = ethers.utils.zeroPad( + ethers.utils.arrayify(pubkey), + 32 + ); + const indexInt = index.toNumber(); + console.debug( + "IDCommitment registered in tree", + idCommitment, + indexInt + ); + latestMembershipSpan.innerHTML = indexInt; + } catch (err) { + console.error(err); // TODO: the merkle tree can be in a wrong state. The app should be disabled + } + }, + disableIfNotGoerli(chainId) { + if (!isGoerliChain(chainId)) { + window.alert("Switch to Goerli"); + + registerButton.disabled = true; + retrieveRLNDetailsButton.disabled = true; + } else { + retrieveRLNDetailsButton.disabled = false; + } + }, + enableRegisterButtonForGoerli(chainId) { + registerButton.disabled = isGoerliChain(chainId) ? false : true; + }, + setAccount(accounts) { + addressDiv.innerText = accounts.length ? accounts[0] : ""; + }, + onConnectWallet(fn) { + connectWalletButton.addEventListener("click", async () => { + await fn(); + importFromWalletButton.disabled = false; + }); + }, + onRetrieveDetails(fn) { + retrieveRLNDetailsButton.addEventListener("click", async () => { + await fn(); + }); + }, + onManualImport(fn) { + importManually.addEventListener("click", () => { + const idKey = utils.hexToBytes(identityKeyInput.value); + const idCommitment = utils.hexToBytes(commitmentKeyInput.value); + + const membershipId = membershipIdInput.value; + const membershipKey = new MembershipKey(idKey, idCommitment); + + fn(membershipId, membershipKey); + }); + }, + onWalletImport(fn) { + importFromWalletButton.addEventListener("click", async () => { + await fn(); + }); + }, + onRegister(fn) { + registerButton.addEventListener("click", async () => { + try { + registerButton.disabled = true; + await fn(); + registerButton.disabled = false; + } catch (err) { + alert(err); + registerButton.disabled = false; + } + }); + }, + // UI for Waku + setWakuStatus(text) { + statusDiv.innerText = text; + }, + setSendingStatus(text) { + sendingStatusSpan.innerText = text; + }, + renderMessage(message) { + messagesList.innerHTML += `
  • ${message.msg} - [epoch: ${message.epoch}, proof: ${message.proofState} ]
  • `; + }, + enableDialButton() { + dialButton.disabled = false; + }, + enableChatButtonsIfNickSet() { + if (nicknameInput.value) { + textInput.disabled = false; + sendButton.disabled = false; + } + }, + onDial(fn) { + dialButton.addEventListener("click", async () => { + const multiaddr = remoteMultiAddrInput.value; + + if (!multiaddr) { + this.setWakuStatus("Error: No multiaddr provided."); + return; + } + + await fn(multiaddr); + nicknameInput.disabled = false; + }); + }, + clearMessageArea() { + textInput.value = null; + setTimeout(() => { + this.setSendingStatus(""); + }, 5000); + }, + onSendMessage(fn) { + sendButton.addEventListener("click", async () => { + const nick = nicknameInput.value; + const text = utils.utf8ToBytes(textInput.value); + await fn(nick, text); + }); + }, + }; +} + +function isGoerliChain(id) { + return id === 5; +} From 39eb5abae1fc22a8d11ffa1fdf0bddd0389678af Mon Sep 17 00:00:00 2001 From: Sasha Date: Thu, 13 Apr 2023 01:45:59 +0200 Subject: [PATCH 04/12] align --- examples/rln-js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index 7c40f94f..896ecd9c 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -40,7 +40,7 @@ run() async function run() { const ui = initUI(); const rln = await initRLN(ui); - const waku = await initWaku(ui, rln); + await initWaku(ui, rln); } async function initRLN(ui) { From bda6fdc3d289c6b501da80775b96605f9dfaad64 Mon Sep 17 00:00:00 2001 From: Sasha Date: Thu, 13 Apr 2023 02:10:12 +0200 Subject: [PATCH 05/12] udpate waku versions --- examples/rln-js/index.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index 896ecd9c..e94738b7 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -1,10 +1,10 @@ -import { utils } from "https://unpkg.com/js-waku@0.30.0/bundle/index.js"; -import { createLightNode } from "https://unpkg.com/js-waku@0.30.0/bundle/lib/create_waku.js"; -import { waitForRemotePeer } from "https://unpkg.com/js-waku@0.30.0/bundle/lib/wait_for_remote_peer.js"; +import * as utils from "https://unpkg.com/@waku/utils@0.0.4/bundle/bytes.js"; +import { createLightNode } from "https://unpkg.com/@waku/create@0.0.12/bundle/index.js"; import { - EncoderV0, - DecoderV0, -} from "https://unpkg.com/js-waku@0.30.0/bundle/lib/waku_message/version_0.js"; + createEncoder, + createDecoder, + waitForRemotePeer, +} from "https://unpkg.com/@waku/core@0.0.16/bundle/index.js"; import { protobuf } from "https://taisukef.github.io/protobuf-es.js/dist/protobuf-es.js"; import { create, @@ -100,7 +100,7 @@ async function initRLN(ui) { membershipKey = key; encoder = new RLNEncoder( - new EncoderV0(ContentTopic), + createEncoder(ContentTopic), rlnInstance, membershipId, membershipKey @@ -126,7 +126,7 @@ async function initRLN(ui) { if (membershipId) { encoder = new RLNEncoder( - new EncoderV0(ContentTopic), + createEncoder(ContentTopic), rlnInstance, membershipId, membershipKey @@ -256,7 +256,7 @@ async function initWaku(ui, rln) { const decoder = new RLNDecoder( rln.rlnInstance, - new DecoderV0(ContentTopic) + createDecoder(ContentTopic) ); await node.filter.subscribe([decoder], onFilterMessage); From ec6a65a10f7c3f453bcd2f4783644c76ff275730 Mon Sep 17 00:00:00 2001 From: Sasha Date: Thu, 13 Apr 2023 02:30:04 +0200 Subject: [PATCH 06/12] fix libp2p issue --- examples/rln-js/index.html | 1 + examples/rln-js/index.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/rln-js/index.html b/examples/rln-js/index.html index f956250a..efeeae1e 100644 --- a/examples/rln-js/index.html +++ b/examples/rln-js/index.html @@ -131,6 +131,7 @@

    Waku

    Messages

      + diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index e94738b7..d5c1f81a 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -246,9 +246,11 @@ async function initWaku(ui, rln) { verifyMessageAndRender(wakuMessage); }; - ui.onDial(async (multiaddr) => { + ui.onDial(async (ma) => { ui.setWakuStatus("Dialing peer."); + // TODO(@weboko): move this fix into Waku.dial + const multiaddr = MultiformatsMultiaddr.multiaddr(ma); await node.dial(multiaddr, ["filter", "lightpush"]); await waitForRemotePeer(node, ["filter", "lightpush"]); @@ -276,7 +278,7 @@ async function initWaku(ui, rln) { console.log("Sending message with proof..."); ui.setSendingStatus("sending..."); - await node.lightPush.push(rln.encoder, { payload, timestamp }); + await node.lightPush.send(rln.encoder, { payload, timestamp }); ui.setSendingStatus("sent!"); console.log("Message sent!"); From 863bc88400aa1bc2e1eaf70ba1a00ce25be160ae Mon Sep 17 00:00:00 2001 From: Sasha Date: Thu, 13 Apr 2023 20:15:45 +0200 Subject: [PATCH 07/12] change block number --- examples/rln-js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index d5c1f81a..7f41bd14 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -23,7 +23,7 @@ const ProtoChatMessage = new protobuf.Type("ChatMessage") .add(new protobuf.Field("nick", 2, "string")) .add(new protobuf.Field("text", 3, "bytes")); -const rlnDeployBlk = 8818900; +const rlnDeployBlk = 8824425; const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; const SIGNATURE_MESSAGE = From d7f93cc36d3af5fa47159b698e37f9dd356bb9cc Mon Sep 17 00:00:00 2001 From: Sasha Date: Sat, 15 Apr 2023 01:06:15 +0200 Subject: [PATCH 08/12] fix small issues, bump rln-js version --- examples/rln-js/index.js | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index 7f41bd14..dc039d20 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -12,7 +12,7 @@ import { RLNDecoder, RLNEncoder, RLNContract, -} from "https://unpkg.com/@waku/rln@0.0.13-fae4bea/bundle/index.js"; +} from "https://unpkg.com/@waku/rln@0.0.14/bundle/index.js"; import { ethers } from "https://unpkg.com/ethers@5.7.2/dist/ethers.esm.min.js"; const ContentTopic = "/toy-chat/2/luzhou/proto"; @@ -23,7 +23,7 @@ const ProtoChatMessage = new protobuf.Type("ChatMessage") .add(new protobuf.Field("nick", 2, "string")) .add(new protobuf.Field("text", 3, "bytes")); -const rlnDeployBlk = 8824425; +const rlnDeployBlk = 8828313; const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; const SIGNATURE_MESSAGE = @@ -44,6 +44,11 @@ async function run() { } async function initRLN(ui) { + const result = { + encoder: undefined, + rlnInstance: undefined, + }; + const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); ui.setRlnStatus("WASM Blob download in progress..."); @@ -90,7 +95,6 @@ async function initRLN(ui) { }); }); - let encoder; let signature; let membershipId; let membershipKey; @@ -99,8 +103,11 @@ async function initRLN(ui) { membershipId = id; membershipKey = key; - encoder = new RLNEncoder( - createEncoder(ContentTopic), + result.encoder = new RLNEncoder( + createEncoder({ + ephemeral: false, + contentTopic: ContentTopic, + }), rlnInstance, membershipId, membershipKey @@ -125,8 +132,11 @@ async function initRLN(ui) { }); if (membershipId) { - encoder = new RLNEncoder( - createEncoder(ContentTopic), + result.encoder = new RLNEncoder( + createEncoder({ + ephemeral: false, + contentTopic: ContentTopic, + }), rlnInstance, membershipId, membershipKey @@ -182,10 +192,7 @@ async function initRLN(ui) { ui.enableDialButton(); }); - return { - encoder, - rlnInstance, - }; + return result; } async function initWaku(ui, rln) { @@ -196,7 +203,7 @@ async function initWaku(ui, rln) { await node.start(); ui.setWakuStatus("Waku node started."); - const verifyMessageAndRender = (message) => { + const verifyMessage = (message) => { if (message.proofState === "verifying...") { try { console.log("Verifying proof without roots"); @@ -216,7 +223,6 @@ async function initWaku(ui, rln) { console.error("Error verifying proof:", e); } - ui.renderMessage(message); console.log("Verifying proof with roots", message.verify()); } }; @@ -243,7 +249,8 @@ async function initWaku(ui, rln) { [${time.toISOString()}] `; - verifyMessageAndRender(wakuMessage); + verifyMessage(wakuMessage); + ui.renderMessage(wakuMessage); }; ui.onDial(async (ma) => { @@ -261,7 +268,7 @@ async function initWaku(ui, rln) { createDecoder(ContentTopic) ); - await node.filter.subscribe([decoder], onFilterMessage); + await node.filter.subscribe(decoder, onFilterMessage); ui.setWakuStatus("Waku node subscribed."); ui.enableChatButtonsIfNickSet(); From 967f097d03d56042e984e4777ad93c25b5d0a9a2 Mon Sep 17 00:00:00 2001 From: Sasha Date: Mon, 17 Apr 2023 21:22:14 +0200 Subject: [PATCH 09/12] use registerFromMembership api --- examples/rln-js/index.js | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index dc039d20..4c7f4ff4 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -150,34 +150,10 @@ async function initRLN(ui) { }); ui.onRegister(async () => { - let event; - ui.setRlnStatus("Trying to register..."); - if (signature) { - event = await rlnContract.registerMember(rlnInstance, signature); - } else { - // if user imports credentials manually - // TODO(@weboko): add logic to cover it in RLNContract - const idCommitment = membershipKey.IDCommitment; - const reversedArray = idCommitment.slice().reverse(); - const pubkey = ethers.utils.hexlify(reversedArray).toString(); - - const price = await rlnContract.MEMBERSHIP_DEPOSIT(); - - const signer = provider.getSigner(); - const rlnContractWithSigner = rlnContract.connect(signer); - - const txResponse = await rlnContractWithSigner.register(pubkey, { - value: price, - }); - console.log("Transaction broadcasted:", txResponse); - - const txReceipt = await txResponse.wait(); - - console.log("Transaction receipt", txReceipt); - - event = txReceipt.events[0]; - } + const event = signature + ? await rlnContract.registerMember(rlnInstance, signature) + : await rlnContract.registerMemberFromMembershipKey(membershipKey); // Update membershipId membershipId = event.args.index.toNumber(); From 7d473f3ae9dc5b45d13c08827b986ef3f91ea86e Mon Sep 17 00:00:00 2001 From: Sasha Date: Tue, 25 Apr 2023 23:13:47 +0200 Subject: [PATCH 10/12] disable retrieve button when fetching members --- examples/rln-js/index.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index 4c7f4ff4..1c755a03 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -23,7 +23,7 @@ const ProtoChatMessage = new protobuf.Type("ChatMessage") .add(new protobuf.Field("nick", 2, "string")) .add(new protobuf.Field("text", 3, "bytes")); -const rlnDeployBlk = 8828313; +const rlnDeployBlk = 7109391; const rlnAddress = "0x4252105670fe33d2947e8ead304969849e64f2a6"; const SIGNATURE_MESSAGE = @@ -80,7 +80,10 @@ async function initRLN(ui) { ui.onRetrieveDetails(async () => { const filter = rlnContract.contract.filters.MemberRegistered(); + ui.disableRetrieveButton(); await rlnContract.fetchMembers(rlnInstance, rlnDeployBlk); + ui.enableRetrieveButton(); + rlnContract.subscribeToMembers(rlnInstance); const last = rlnContract.members.at(-1); @@ -373,11 +376,17 @@ function initUI() { window.alert("Switch to Goerli"); registerButton.disabled = true; - retrieveRLNDetailsButton.disabled = true; + this.disableRetrieveButton(); } else { - retrieveRLNDetailsButton.disabled = false; + this.enableRetrieveButton(); } }, + enableRetrieveButton() { + retrieveRLNDetailsButton.disabled = false; + }, + disableRetrieveButton() { + retrieveRLNDetailsButton.disabled = true; + }, enableRegisterButtonForGoerli(chainId) { registerButton.disabled = isGoerliChain(chainId) ? false : true; }, From 094686962a69645b53e8b1c37053375ccf647aec Mon Sep 17 00:00:00 2001 From: Sasha Date: Fri, 28 Apr 2023 01:25:34 +0200 Subject: [PATCH 11/12] ignore mac file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d59dd810..bb066d42 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dist build node_modules yarn.lock +.DS_Store From b59b1ad234f2e329c4e3fcfceb2cfff6cef2cb6d Mon Sep 17 00:00:00 2001 From: Sasha Date: Fri, 28 Apr 2023 01:30:14 +0200 Subject: [PATCH 12/12] use latest @waku/rln --- examples/rln-js/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rln-js/index.js b/examples/rln-js/index.js index 1c755a03..26e2aaa1 100644 --- a/examples/rln-js/index.js +++ b/examples/rln-js/index.js @@ -12,7 +12,7 @@ import { RLNDecoder, RLNEncoder, RLNContract, -} from "https://unpkg.com/@waku/rln@0.0.14/bundle/index.js"; +} from "https://unpkg.com/@waku/rln@0.0.14-7e0966a/bundle/index.js"; import { ethers } from "https://unpkg.com/ethers@5.7.2/dist/ethers.esm.min.js"; const ContentTopic = "/toy-chat/2/luzhou/proto"; @@ -81,7 +81,7 @@ async function initRLN(ui) { const filter = rlnContract.contract.filters.MemberRegistered(); ui.disableRetrieveButton(); - await rlnContract.fetchMembers(rlnInstance, rlnDeployBlk); + await rlnContract.fetchMembers(rlnInstance, { fromBlock: rlnDeployBlk }); ui.enableRetrieveButton(); rlnContract.subscribeToMembers(rlnInstance);