├── webapp ├── .gitignore ├── .env.example ├── package.json ├── index.html ├── vite.config.js ├── json_abi │ └── CommentVerifier.json └── app.js ├── relayer ├── .gitignore ├── .env.example ├── package.json ├── json_abi │ └── CommentVerifier.json ├── relayer.js └── package-lock.json ├── screenshot.png ├── circuit ├── Nargo.toml ├── src │ └── main.nr └── target │ ├── circuit.json │ └── debug_circuit.json ├── contracts └── CommentVerifier.sol └── README.md /webapp/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /relayer/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /webapp/.env.example: -------------------------------------------------------------------------------- 1 | CHAIN_ID = "534351" 2 | COMMENT_VERIFIER_ADDRESS = "0x123abc" -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Turupawn/EcrecoverInclusionProof/HEAD/screenshot.png -------------------------------------------------------------------------------- /relayer/.env.example: -------------------------------------------------------------------------------- 1 | RPC_URL="https://sepolia-rpc.scroll.io" 2 | COMMENT_VERIFIER_ADDRESS = "0x123abc" 3 | RELAYER_PRIVATE_KEY ="123abc" 4 | RELAYER_ADDRESS = "0x123abv" -------------------------------------------------------------------------------- /circuit/Nargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "circuit" 3 | type = "bin" 4 | authors = [""] 5 | compiler_version = "0.22.0" 6 | 7 | [dependencies] 8 | ecrecover = { tag = "v0.19.0", git = "https://github.com/colinnielsen/ecrecover-noir" } -------------------------------------------------------------------------------- /relayer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "relayer", 3 | "version": "1.0.0", 4 | "description": "huh", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "node relayer.js" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "cors": "^2.8.5", 15 | "dotenv": "^10.0.0", 16 | "ethers": "^6.9.0", 17 | "express": "^4.18.2", 18 | "node-fetch": "^3.1.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /webapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "verification-counter", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "vite --open", 9 | "build": "vite build", 10 | "preview": "vite preview", 11 | "relayer": "node relayer/relayer.js" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "@noir-lang/backend_barretenberg": "^0.22.0", 17 | "@noir-lang/noir_js": "^0.22.0", 18 | "dotenv": "^16.3.1", 19 | "@alch/alchemy-web3": "^1.1.7", 20 | "cors": "^2.8.5", 21 | "node-fetch": "^3.1.0" 22 | }, 23 | "devDependencies": { 24 | "rollup-plugin-copy": "^3.5.0", 25 | "vite": "^4.5.0", 26 | "vite-plugin-environment": "^1.1.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /circuit/src/main.nr: -------------------------------------------------------------------------------- 1 | use dep::std::ecdsa_secp256k1::verify_signature; 2 | use dep::std; 3 | use dep::std::scalar_mul; 4 | use dep::std::hash; 5 | use dep::ecrecover; 6 | 7 | fn main( 8 | pub_key_x: [u8; 32], 9 | pub_key_y: [u8; 32], 10 | signature: [u8; 64], 11 | hashed_message: pub [u8; 32], 12 | root: pub Field, 13 | index: Field, 14 | hash_path: [Field; 2] 15 | ) { 16 | // First, let's check if signature is vaild and corresponds to the public key provided 17 | let valid_signature = verify_signature(pub_key_x, pub_key_y, signature, hashed_message); 18 | assert(valid_signature); 19 | 20 | // Grab the ethereum address from the public key 21 | let key = ecrecover::secp256k1::PubKey::from_xy(pub_key_x, pub_key_y); 22 | let leaf = key.to_eth_address(); 23 | 24 | // Check if the address is part of the merkle tree 25 | let computedRoot = std::merkle::compute_merkle_root(leaf, index, hash_path); 26 | 27 | assert (root == computedRoot); 28 | } -------------------------------------------------------------------------------- /webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Aztec Noir - Scroll Demo

4 |

Anon Message Board

5 | 6 | 7 |

8 |

9 | 10 |

Send a comment

11 | message: 12 | 13 | 14 |

Comments

15 |
16 | 17 |

18 |

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | -------------------------------------------------------------------------------- /webapp/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import copy from 'rollup-plugin-copy'; 3 | import fs from 'fs'; 4 | import path from 'path'; 5 | import EnvironmentPlugin from 'vite-plugin-environment' 6 | 7 | const wasmContentTypePlugin = { 8 | name: 'wasm-content-type-plugin', 9 | configureServer(server) { 10 | server.middlewares.use(async (req, res, next) => { 11 | if (req.url.endsWith('.wasm')) { 12 | res.setHeader('Content-Type', 'application/wasm'); 13 | const newPath = req.url.replace('deps', 'dist'); 14 | const targetPath = path.join(__dirname, newPath); 15 | const wasmContent = fs.readFileSync(targetPath); 16 | return res.end(wasmContent); 17 | } 18 | next(); 19 | }); 20 | }, 21 | }; 22 | 23 | export default defineConfig(({ command }) => { 24 | if (command === 'serve') { 25 | return { 26 | plugins: [ 27 | copy({ 28 | targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], 29 | copySync: true, 30 | hook: 'buildStart', 31 | }), 32 | command === 'serve' ? wasmContentTypePlugin : [], 33 | EnvironmentPlugin(['COMMENT_VERIFIER_ADDRESS','CHAIN_ID']), 34 | ], 35 | }; 36 | } 37 | 38 | return {}; 39 | }); -------------------------------------------------------------------------------- /relayer/json_abi/CommentVerifier.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "bytes", 6 | "name": "_proof", 7 | "type": "bytes" 8 | }, 9 | { 10 | "internalType": "bytes32[]", 11 | "name": "_publicInputs", 12 | "type": "bytes32[]" 13 | }, 14 | { 15 | "internalType": "string", 16 | "name": "comment", 17 | "type": "string" 18 | } 19 | ], 20 | "name": "sendProof", 21 | "outputs": [], 22 | "stateMutability": "nonpayable", 23 | "type": "function" 24 | }, 25 | { 26 | "inputs": [ 27 | { 28 | "internalType": "address", 29 | "name": "verifierAddress", 30 | "type": "address" 31 | }, 32 | { 33 | "internalType": "bytes32", 34 | "name": "_merkleRoot", 35 | "type": "bytes32" 36 | } 37 | ], 38 | "stateMutability": "nonpayable", 39 | "type": "constructor" 40 | }, 41 | { 42 | "inputs": [], 43 | "name": "commentCount", 44 | "outputs": [ 45 | { 46 | "internalType": "uint256", 47 | "name": "", 48 | "type": "uint256" 49 | } 50 | ], 51 | "stateMutability": "view", 52 | "type": "function" 53 | }, 54 | { 55 | "inputs": [ 56 | { 57 | "internalType": "uint256", 58 | "name": "commentCount", 59 | "type": "uint256" 60 | } 61 | ], 62 | "name": "comments", 63 | "outputs": [ 64 | { 65 | "internalType": "string", 66 | "name": "comment", 67 | "type": "string" 68 | } 69 | ], 70 | "stateMutability": "view", 71 | "type": "function" 72 | }, 73 | { 74 | "inputs": [ 75 | { 76 | "internalType": "string", 77 | "name": "comment", 78 | "type": "string" 79 | } 80 | ], 81 | "name": "hashCommentMessage", 82 | "outputs": [ 83 | { 84 | "internalType": "bytes32", 85 | "name": "", 86 | "type": "bytes32" 87 | } 88 | ], 89 | "stateMutability": "pure", 90 | "type": "function" 91 | } 92 | ] -------------------------------------------------------------------------------- /webapp/json_abi/CommentVerifier.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "bytes", 6 | "name": "_proof", 7 | "type": "bytes" 8 | }, 9 | { 10 | "internalType": "bytes32[]", 11 | "name": "_publicInputs", 12 | "type": "bytes32[]" 13 | }, 14 | { 15 | "internalType": "string", 16 | "name": "comment", 17 | "type": "string" 18 | } 19 | ], 20 | "name": "sendProof", 21 | "outputs": [], 22 | "stateMutability": "nonpayable", 23 | "type": "function" 24 | }, 25 | { 26 | "inputs": [ 27 | { 28 | "internalType": "address", 29 | "name": "verifierAddress", 30 | "type": "address" 31 | }, 32 | { 33 | "internalType": "bytes32", 34 | "name": "_merkleRoot", 35 | "type": "bytes32" 36 | } 37 | ], 38 | "stateMutability": "nonpayable", 39 | "type": "constructor" 40 | }, 41 | { 42 | "inputs": [], 43 | "name": "commentCount", 44 | "outputs": [ 45 | { 46 | "internalType": "uint256", 47 | "name": "", 48 | "type": "uint256" 49 | } 50 | ], 51 | "stateMutability": "view", 52 | "type": "function" 53 | }, 54 | { 55 | "inputs": [ 56 | { 57 | "internalType": "uint256", 58 | "name": "commentCount", 59 | "type": "uint256" 60 | } 61 | ], 62 | "name": "comments", 63 | "outputs": [ 64 | { 65 | "internalType": "string", 66 | "name": "comment", 67 | "type": "string" 68 | } 69 | ], 70 | "stateMutability": "view", 71 | "type": "function" 72 | }, 73 | { 74 | "inputs": [ 75 | { 76 | "internalType": "string", 77 | "name": "comment", 78 | "type": "string" 79 | } 80 | ], 81 | "name": "hashCommentMessage", 82 | "outputs": [ 83 | { 84 | "internalType": "bytes32", 85 | "name": "", 86 | "type": "bytes32" 87 | } 88 | ], 89 | "stateMutability": "pure", 90 | "type": "function" 91 | } 92 | ] -------------------------------------------------------------------------------- /relayer/relayer.js: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv" 2 | import fs from "fs" 3 | import cors from "cors" 4 | import express from "express" 5 | import { ethers } from 'ethers'; 6 | 7 | const app = express() 8 | dotenv.config(); 9 | app.use(cors()) 10 | 11 | const JSON_CONTRACT_PATH = "./json_abi/CommentVerifier.json" 12 | const PORT = 8080 13 | var contract 14 | var provider 15 | var signer 16 | 17 | const { RPC_URL, COMMENT_VERIFIER_ADDRESS, RELAYER_PRIVATE_KEY, RELAYER_ADDRESS } = process.env; 18 | 19 | const loadContract = async (data) => { 20 | data = JSON.parse(data); 21 | contract = new ethers.Contract(COMMENT_VERIFIER_ADDRESS, data, signer); 22 | } 23 | 24 | async function initAPI() { 25 | provider = new ethers.JsonRpcProvider(RPC_URL); 26 | signer = new ethers.Wallet(RELAYER_PRIVATE_KEY, provider); 27 | 28 | fs.readFile(JSON_CONTRACT_PATH, 'utf8', function (err,data) { 29 | if (err) { 30 | return console.log(err); 31 | } 32 | loadContract(data) 33 | }); 34 | 35 | app.listen(PORT, () => { 36 | console.log(`Listening to port ${PORT}`) 37 | }) 38 | } 39 | 40 | async function relayMessage(proof, hashedMessage, comment) 41 | { 42 | const transaction = { 43 | from: RELAYER_ADDRESS, 44 | to: COMMENT_VERIFIER_ADDRESS, 45 | value: '0', 46 | gasPrice: "700000000", // 0.7 gwei 47 | nonce: await provider.getTransactionCount(RELAYER_ADDRESS), 48 | chainId: "534351", 49 | data: contract.interface.encodeFunctionData( 50 | "sendProof",[proof, hashedMessage, comment] 51 | ) 52 | }; 53 | const signedTransaction = await signer.populateTransaction(transaction); 54 | const transactionResponse = await signer.sendTransaction(signedTransaction); 55 | console.log('🎉 The hash of your transaction is:', transactionResponse.hash); 56 | } 57 | 58 | app.get('/relay', (req, res) => { 59 | var proof = req.query["proof"] 60 | var hashedMessage = req.query["hashedMessage"].split(',') 61 | var comment = req.query["comment"] 62 | 63 | relayMessage(proof, hashedMessage, comment) 64 | 65 | res.setHeader('Content-Type', 'application/json'); 66 | res.send({ 67 | "message": "the proof was relayed" 68 | }) 69 | }) 70 | initAPI() -------------------------------------------------------------------------------- /contracts/CommentVerifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.19; 3 | 4 | interface IUltraVerifier { 5 | function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); 6 | } 7 | 8 | abstract contract Utils { 9 | // UINT TO STRING 10 | // From OpenZeppelin 11 | // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol 12 | function log10(uint256 value) internal pure returns (uint256) { 13 | uint256 result = 0; 14 | unchecked { 15 | if (value >= 10 ** 64) { 16 | value /= 10 ** 64; 17 | result += 64; 18 | } 19 | if (value >= 10 ** 32) { 20 | value /= 10 ** 32; 21 | result += 32; 22 | } 23 | if (value >= 10 ** 16) { 24 | value /= 10 ** 16; 25 | result += 16; 26 | } 27 | if (value >= 10 ** 8) { 28 | value /= 10 ** 8; 29 | result += 8; 30 | } 31 | if (value >= 10 ** 4) { 32 | value /= 10 ** 4; 33 | result += 4; 34 | } 35 | if (value >= 10 ** 2) { 36 | value /= 10 ** 2; 37 | result += 2; 38 | } 39 | if (value >= 10 ** 1) { 40 | result += 1; 41 | } 42 | } 43 | return result; 44 | } 45 | 46 | bytes16 private constant HEX_DIGITS = "0123456789abcdef"; 47 | 48 | function toString(uint256 value) internal pure returns (string memory) { 49 | unchecked { 50 | uint256 length = log10(value) + 1; 51 | string memory buffer = new string(length); 52 | uint256 ptr; 53 | /// @solidity memory-safe-assembly 54 | assembly { 55 | ptr := add(buffer, add(32, length)) 56 | } 57 | while (true) { 58 | ptr--; 59 | /// @solidity memory-safe-assembly 60 | assembly { 61 | mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) 62 | } 63 | value /= 10; 64 | if (value == 0) break; 65 | } 66 | return buffer; 67 | } 68 | } 69 | 70 | // CONCATENATE HEX ARRAY 71 | // From ChatGPT 72 | function concatenateHexArray(bytes32[] memory hexArray, uint start, uint end) internal pure returns (bytes32) { 73 | bytes32 result; 74 | for (uint256 i = start; i < end; i++) { 75 | result = result << 8 | hexArray[i]; 76 | } 77 | return result; 78 | } 79 | } 80 | 81 | contract CommentVerifier is Utils { 82 | uint public commentCount; 83 | mapping(uint commentCount => string comment) public comments; 84 | IUltraVerifier ultraVerifier; 85 | bytes32 merkleRoot; 86 | 87 | constructor(address verifierAddress, bytes32 _merkleRoot) { 88 | ultraVerifier = IUltraVerifier(verifierAddress); 89 | merkleRoot = _merkleRoot; 90 | } 91 | 92 | function hashCommentMessage(string memory comment) public pure returns(bytes32) { 93 | return keccak256(abi.encodePacked( 94 | "\x19Ethereum Signed Message:\n", 95 | toString(bytes(comment).length), 96 | comment)); 97 | } 98 | 99 | function sendProof(bytes calldata _proof, bytes32[] calldata _publicInputs, string memory comment) public 100 | { 101 | require(concatenateHexArray(_publicInputs, 0, 32) == hashCommentMessage(comment), "Invalid message hash"); 102 | require(_publicInputs[32] == merkleRoot, "Invalid merkle root"); 103 | ultraVerifier.verify(_proof, _publicInputs); 104 | comments[commentCount] = comment; 105 | commentCount += 1; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Message board with anonymity set inclusion proofs. 2 | 3 | # On-chain Privacy DApp Demo using inclusion proofs 4 | 5 | This demo showcases all the parts needed to create a privacy preserving DApp with good UX which are: 6 | * A circuit 7 | * A smart contract 8 | * A relayer 9 | * A webapp 10 | 11 | ## ✅Features 12 | 13 | | Feature | Supported | 14 | |----------|------------ | 15 | | Aztec Noir circuit | ✅ | 16 | | Solidity verifier | ✅ | 17 | | ECDSA verification circuit | ✅ | 18 | | Merkle tree membership proof | ✅ | 19 | | Prover on browser (WASM) | ✅ | 20 | | Ethers.js 6.9 relayer | ✅ | 21 | | MIT license | ✅ | 22 | 23 | ## 🚀How to launch 24 | 25 | ### Step 1. Generate and deploy the Solidity verifier 26 | 27 | Make sure you installed Nargo `0.22.0` as detailed below: 28 | 29 |
30 | On Linux 31 | 32 | ```bash 33 | mkdir -p $HOME/.nargo/bin && \ 34 | curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ 35 | tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ 36 | echo 'export PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ 37 | source ~/.bashrc 38 | ``` 39 |
40 | 41 |
42 | On MAC 43 | 44 | ```bash 45 | mkdir -p $HOME/.nargo/bin && \ 46 | curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-apple-darwin.tar.gz && \ 47 | tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ 48 | echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ 49 | source ~/.zshrc 50 | ``` 51 |
52 | 53 | Now generate the Solidity verifier. 54 | 55 | ```bash 56 | cd circuit 57 | nargo codegen-verifier 58 | ``` 59 | 60 | This will generate a Solidity file located at `circuit/contract/circuit/plonk_vk.sol`. Deploy it on an EVM on-chain. 61 | 62 | ### Before you continue 63 | 64 | Make sure you generate your anonymity set. Usually you may want to generate them on a library provided by Aztec that has the implementation of Pedersen hashing method that matches their prover library. However that library has not been released yet. So for the sake of compatibility we'll use the following circuit to print the merkle tree. 65 | 66 | ``` 67 | use dep::std::ecdsa_secp256k1::verify_signature; 68 | use dep::std; 69 | use dep::std::scalar_mul; 70 | use dep::std::hash; 71 | 72 | fn main(index : Field, 73 | leafLeft: Field, 74 | leafRight: Field 75 | ) { 76 | let root = std::merkle::compute_merkle_root(leafLeft, index, [leafRight]); 77 | std::println(root); 78 | } 79 | ``` 80 | 81 | In this example we'll use the following merkle tree with a few ethereum accounts I control. When you generate your own merkle tree make sure to update the `sendProof` function on the `app.js` file. And also, when you launch your `CommentVerifier` contract pass as paramater your merkle root. 82 | 83 | ``` 84 | └─ 0x2a550743aa7151b3324482a03b2961ec4b038672a701f8ad0051b2c9d2e6c4c0 85 | ├─ 0x1476e5c502f3a532e7c36640e88eebf769ae99d6c50f3be65279ca937b795a3d 86 | │ ├─ 0x000000000000000000000000707e55a12557E89915D121932F83dEeEf09E5d70 87 | │ └─ 0x000000000000000000000000bef34f2FCAe62dC3404c3d01AF65a7784c9c4A19 88 | └─ 0x00000000000000000000000008966BfFa14A7d0d7751355C84273Bb2eaF20FC3 89 | └─ 0x00000000000000000000000008966BfFa14A7d0d7751355C84273Bb2eaF20FC3 90 | ``` 91 | 92 | ### Step 2. Deploy the verifier contract 93 | 94 | Now deploy the `CommentVerifier` contract located at `contracts/CommentVerifier.sol`. Pass the Verifier contract you just generated as constructor parameter. 95 | 96 | ### Step 3. Launch the Relayer 97 | 98 | Let's launch the relayer first. Fill the `.env` file based on `.env.example` on the `relayer/` directory and run the following. 99 | 100 | ```bash 101 | cd relayer 102 | npm install 103 | npm start 104 | ``` 105 | 106 | ### Setp 4. Launch the webapp and verify a proof 107 | 108 | Open a new terminal and launch the webapp. Now fill the `.env` file based on `.env.example` on the `webapp/`, the run the following. 109 | 110 | ```bash 111 | cd webapp 112 | npm install 113 | npm start 114 | ``` 115 | 116 | The webapp will automatically open on your browser. Now you will be able to generate proofs on your browser and send them to the relayer for on-chain verification. 117 | 118 | ## ⚠️Known issues (PRs welcome) 119 | 120 | * This demo uses normal wallet signatures hence proofs are not nullifiable. See [plume](https://github.com/plume-sig/zk-nullifier-sig) 121 | -------------------------------------------------------------------------------- /circuit/target/circuit.json: -------------------------------------------------------------------------------- 1 | {"noir_version":"0.22.0+3fae4a03fded4e3f5065e7461c563f7e39745604","hash":214772706270574836,"abi":{"parameters":[{"name":"pub_key_x","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"pub_key_y","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"signature","type":{"kind":"array","length":64,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"hashed_message","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"public"},{"name":"root","type":{"kind":"field"},"visibility":"public"},{"name":"index","type":{"kind":"field"},"visibility":"private"},{"name":"hash_path","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"private"}],"param_witnesses":{"hash_path":[{"start":163,"end":165}],"hashed_message":[{"start":129,"end":161}],"index":[{"start":162,"end":163}],"pub_key_x":[{"start":1,"end":33}],"pub_key_y":[{"start":33,"end":65}],"root":[{"start":161,"end":162}],"signature":[{"start":65,"end":129}]},"return_type":null,"return_witnesses":[]},"bytecode":"H4sIAAAAAAAA/+2dBXRU1xaG7yQQIY47AUoL1bkRklQgQKm7UBdSQqlC27TUqbu7l/Lq7u7u7q7Pve7vP8n+y85+QXOGNWf13rW+teefSc79z557z95D7nAnpqLohahtw8MoR2KB0jlG5xrdxeiuRucZnW90gdGFRnczusjoYqNLjC41uszocqMrjO5udA+jexrdy+jeRvcxuq/R/Yzub/QAowcaPcjowUYPMbrS6KFGDzN6uNFLGT3C6KWNXsbokUaPMnpZo5czenmjVzB6RaNXMjptdGx0ldHVRtcYXWv0aKPrjK43usHolY1exehVjV7N6DFGjzW60ehxRo83eoLRqxs90eg1jF7T6LWMXtvodYxe1+j1jF7f6A2M3tDojYze2OhNjN7U6M2M3tzoSUZvYfSWRm9l9NZGb2P0tkZvZ/T2Ru9g9I5GTza6yeidjJ5idLPRU43e2ehpRu9i9K5G72b07kbvYfSeRk83eobRexm9t9H7GN1i9L5G72f0TKP3N/oAow80+iCjDzb6EKMPNXqW0YcZfbjRRxh9pNFHGX200ccYfazRxxl9vNEnGH2i0ScZfbLRpxh9qtGnGX260WcYfabRZxl9ttHnGH2u0ecZfb7RFxh9odEXGX2x0ZcYfanRs5V2vVdl1Lal5Pkciez72O+xz2N/x76OsI9j/8a+jf0a+zT2Z+zL2I+xD2P/xb6L/Rb7LPZX7KvYT7GPYv/Evon9Evsk9kfsiypVdNtQ0cMksv9h38N+h30O+5uREtnPsI9h/8K+hf0K+xT2J+xL2I+wD2H/wb6D/Qb7DPYX7CvYT7CPYP/AvoH9AvsE9geNKrptnOjxEtkHsP6z7rPes86vJZF1nfWcdZz1m3Wb9Zp1mvWZdZn1mHWY9Zd1l/WWdZb1lXWV9ZR1lPWTdZP1knVyR4mTJTZJZB1k/WPdY71jnZsmkXWN9Yx1jPWLdYv1inWK9Yl1ifWIdYj1h3WH9YZ1hvWFdYX1hHWE9YN1g/WCdeKwqP35wPrAusB6wDrA9Z/rPtf74yRyfee6zvWc6zjXb67bXK+5TnN95rrM9ZjrMNdfrrtcb7nOcn3lusr1lOso10+um1wvZ0u8Imq/pSQ2Skx3bouvUGNVp0fX1DTXVTXH1fHkdFVDU31tuqa2aXR9XB/X1tdOqaqvrm6ur6mva2hqqEs3xDXVzfHU2obqqTKYW7NzlM/KDHtP+RsrnSmPOQF4zA3AY5cAPHYNwGNeAB7zA/BYEIDHwgA8dgvAY1EAHosD8FgSgMfSADyWBeCxPACPFQF47B6Axx4BeOwZgMdeAXjsHYDHPgF47BuAx34BeOwfgMcBAXgcGIDHQQF4HByAxyEBeKz06HFJ/Fvk0AByOiwAj8MD8LhUAB5HBOBx6QA8LhOAx5EBeBwVgMdlA/C4XAAelw/A4woBeFwxAI8rBeAxHYDHOACPVQF4rA7AY00AHmsD8Dg6AI91AXisD8BjQwAeVw7A4yoBeFw1AI+rBeBxTAAexwbgsdGjx5TyyDGvBFeBq8E14FpwHbge3ABuBDeBm8Et4FZwG7gd3AHuBHeBu8E94F5wH7gfPAAeBA+Bh8Ej4FHwGHgcPAGeBE+Bp8Ez4FnwHHg+avu+5ovgJfAyeAW8Cl4Dr4M3wJvgLfA2eAe8C94D74MPwIfgI/Ax+AR8Cj4Dn4MvwImSFHe9Uk7UfnPXq+V6fj/dfrqo94H76ep5P3lqHn7GrEnnRd6P77TOO2Ohynuueo5566KeY950LFGvR2bsUsl3od95VPE7IHpLGd2oHnP/zkuxVy81rTnttgheipWXIq9e2o7DEr9jth6HpZ7HdGOUqZwwf/RepF4vVfkq85yvlNonx6XW/hKvidfEa+I18Zp4TbwmXhOvidfEa+I18Zp4TbwmXhOvidfEa+I18Zp4TbwmXhOvidfEa+I18Zp4TbwmXhOvidfEa+I18Zp4TbwmXhOvv2+v/D/rtc9C9XMFWeBP541eSvx6ab12mtfOc2x3vfng1Nx9dvO6z6rW72Xo68EblQfuK1f9TFNqrq9hypfna9pbc5EvYxWqXIxYwrnIn08uqlUuRqXm/hxfL1D+i8xz/q+9bzuWuR+OS12s5sG5FHXgr1BF/Tt8LqeD3801+8gPNA/+vbQdU9ZLvvHiYS2J7RNuv3pdH6d8cF+56mfGpNq/Vqo88zsv+lywP+f2Ud65OZit7Ts/FV7HTLv/bqD1XiecF4+BCpUTvj5Rnd9rqu9qcc56XZrUwevcUkY3qsflKn89/c619RjopcZvVPvQ++3td7+x3m9K4D74fK56vLlKUO+5D3/LLz2796pHBz+nH5ea3ylSr/fI8Jx7Kh+NSnNf7jhZRx1Tk1Qt893X6PnqvBSpyNd1b1Ngft69Bzwf9Jrt+7xMqf1wXOoK5Y/PlS1hL/nGi+5P9HoyIuA+QL/uthzlkb9jx/H/fbi2dT8T5wPXPL3ucz+56vU91Tk6Q63rnLNe92d18Dq3+a37um529zvX1nVfr3WNah96v57rTaz3y3Wf++DzuerxoSpBeu1kfunZvVcVHfycflxsfqdIvV6R4TnPa93ivtxxso86pmapdd/zZ8hYz1fnJU/lRa+nfC0Tn6vLo/Z5oYeOPvfrc4vHaKbrTanxR63zw+dKlD/OQ68n/Ixuz3mvbyw3+0X4zt7A6o+Rv8Wb/6DC8a6UN/IqiVdLvEbitRKvk3i9xBsk3ijxJok3S7xF4q0Sb5N4u8Q7JN4p8S6Jd0u8R+K9Eu+TeL/EByQ+KPEhiQ9LfETioxIfk/i4xCckPinxKYlPS3xG4rMSn5P4vMQXJL4o8SWJL0t8ReKrEl+T+LrENyS+KfEtiW9LfEfiuxLfk/i+xA8kfijxI4kfS/xE4qcSP5P4ucQvJLpjq1Jw25/An8FfwF/B38DfwT/AP8G/wL/Bf8B/wZfgK/A1+AZ8C74D34MfwI/gJ/Az+AX86naCgzAFckAu6AK6grxUW1OjT1J7LqU7t8Vz/I2VZgOWD5MFqfY3mfPp2Y3v8L2uuDF95SIT8y6QvPqed4HneXPz/R/CzMnQe724YzVPbdsylb+cDB7fnR2rMJWZXmGhj5l44Qb/Mloonws12lce34vu2XDOLcSsv44W2ucCR/vGY/56ZMuatYBZfxstks/5jvadx/z1zKY1fz6z/j5aZJ/zHO0Hj/nrlW01cx6z/jFaLJ8djvaTx/z1zsaeo4NZ/xwtts//G+0Xj/nrk609m5n1r1GnfLYbLfLYv/TN5p5XzTrVeZ+/jZbjMX/9sv0zg8w614/P1tG6eMxf/xA+c2HWXT32+Xke8zcgkM+sHvv8uIfH/A0MJH8e+9S4l8f8DQokfx77rLiPx/wNDiR/HvuEuJ/H/A0JJH8e61w8wGP+KgPJn8d1Oh7kMX9DA8mfx3UmHuIxf8MCyZ/H8yQe6jF/w5dQ/jrrs5vH/Hk8ZmLf+fP9t64/RJn5G9/oLJ+3+7tKtwzMuy6Q86XI4zHu8b2O6wI4XwozcNysnOXzzs/Q+bJKIOdLscdj3ON7HfvMn3tv3cXL/Hu4WyPcv6UXS3RbSSpqt/n+23mBx96l1PPfzn2fU5dHmbnOZEyWryXuGCrNwLzHBrKWlHk8Lj2+1/HYLD9u3PmSieNmfADXo5VkYN4TAjlfyj0e4x7f63hCBmtvmdTcclV7KxZQe9Od2+LLPL5nFR5zc6SMk5I5u+PLXVzvbqyWJ3lz1xTzJmPuAn33xQF3vbm7UN99scBdlO8u4HdfwnBfNHFfwnBfNHRfwusD+oJ+oD8YAAaCQWAwGBK1Xac8FAwDw8FSYARYGiwDRoJRYFmwHHA3fV8BrAhWcjkArolwN412N2V2Nz12NxV2N+11N8V1N511N3V1N011NyV1N/10N9V0N63kTSHHgfFgAlgdTARrgDXBWmBtsA5YF6wH1gcbgA3BRmBjsAnYFGwGNgeTwBZgS7AV2BpsA7YF24HtwQ5gRzAZNIGdwBTQDKaCncE0sAvYFewGdgd7gD3BdDAD7AX2BvuAFrAv2A/MBPuDA8CB4CBwMDgEHApmgcPAHOA+f10u74XbDgdHAHeMHAWOBseAY8Fx4HhwAjgRnAROBqeAU8Fp4HRwBjgTnAXOBueAc8F54HxwAbgQXAQuBpeAS8FscFk0d0upOEceryZPDhQ9uaWleY8ZLZUt0ysnT5lSOXOXlmmV0/dr3nvq7tNn/g84wXFAEawAAA=="} -------------------------------------------------------------------------------- /webapp/app.js: -------------------------------------------------------------------------------- 1 | import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; 2 | import { Noir } from '@noir-lang/noir_js'; 3 | import circuit from '../circuit/target/circuit.json'; 4 | 5 | const NETWORK_ID = process.env.CHAIN_ID 6 | 7 | const METADA_API_URL = "http://localhost:8080" 8 | 9 | const COMMENT_VERIFIER_ADDRESS = process.env.COMMENT_VERIFIER_ADDRESS; 10 | 11 | const MY_CONTRACT_ABI_PATH = "../json_abi/CommentVerifier.json" 12 | var my_contract 13 | 14 | var accounts 15 | var web3 16 | 17 | function metamaskReloadCallback() { 18 | window.ethereum.on('accountsChanged', (accounts) => { 19 | document.getElementById("web3_message").textContent="Se cambió el account, refrescando..."; 20 | window.location.reload() 21 | }) 22 | window.ethereum.on('networkChanged', (accounts) => { 23 | document.getElementById("web3_message").textContent="Se el network, refrescando..."; 24 | window.location.reload() 25 | }) 26 | } 27 | 28 | const getWeb3 = async () => { 29 | return new Promise((resolve, reject) => { 30 | if(document.readyState=="complete") 31 | { 32 | if (window.ethereum) { 33 | const web3 = new Web3(window.ethereum) 34 | window.location.reload() 35 | resolve(web3) 36 | } else { 37 | reject("must install MetaMask") 38 | document.getElementById("web3_message").textContent="Error: Please connect to Metamask"; 39 | } 40 | }else 41 | { 42 | window.addEventListener("load", async () => { 43 | if (window.ethereum) { 44 | const web3 = new Web3(window.ethereum) 45 | resolve(web3) 46 | } else { 47 | reject("must install MetaMask") 48 | document.getElementById("web3_message").textContent="Error: Please install Metamask"; 49 | } 50 | }); 51 | } 52 | }); 53 | }; 54 | 55 | const getContract = async (web3, address, abi_path) => { 56 | const response = await fetch(abi_path); 57 | const data = await response.json(); 58 | 59 | const netId = await web3.eth.net.getId(); 60 | var contract = new web3.eth.Contract( 61 | data, 62 | address 63 | ); 64 | return contract 65 | } 66 | 67 | async function loadDapp() { 68 | metamaskReloadCallback() 69 | document.getElementById("web3_message").textContent="Please connect to Metamask" 70 | var awaitWeb3 = async function () { 71 | web3 = await getWeb3() 72 | web3.eth.net.getId((err, netId) => { 73 | if (netId == NETWORK_ID) { 74 | var awaitContract = async function () { 75 | my_contract = await getContract(web3, COMMENT_VERIFIER_ADDRESS, MY_CONTRACT_ABI_PATH) 76 | document.getElementById("web3_message").textContent="You are connected to Metamask" 77 | onContractInitCallback() 78 | web3.eth.getAccounts(function(err, _accounts){ 79 | accounts = _accounts 80 | if (err != null) 81 | { 82 | console.error("An error occurred: "+err) 83 | } else if (accounts.length > 0) 84 | { 85 | onWalletConnectedCallback() 86 | document.getElementById("account_address").style.display = "block" 87 | } else 88 | { 89 | document.getElementById("connect_button").style.display = "block" 90 | } 91 | }); 92 | }; 93 | awaitContract(); 94 | } else { 95 | document.getElementById("web3_message").textContent="Please connect to Scroll Sepolia"; 96 | } 97 | }); 98 | }; 99 | awaitWeb3(); 100 | } 101 | 102 | async function connectWallet() { 103 | await window.ethereum.request({ method: "eth_requestAccounts" }) 104 | accounts = await web3.eth.getAccounts() 105 | onWalletConnectedCallback() 106 | } 107 | window.connectWallet=connectWallet; 108 | 109 | const onContractInitCallback = async () => { 110 | var commentCount = await my_contract.methods.commentCount().call() 111 | var contract_state = "commentCount: " + commentCount 112 | 113 | var maxMsgPerPage = 5; 114 | var pageIterator = 0; 115 | var commentsElement = document.getElementById("comments"); 116 | 117 | for(var i=parseInt(commentCount);i>0;i--) 118 | { 119 | var comment = await my_contract.methods.comments(i-1).call() 120 | var paragraph = document.createElement("p"); 121 | paragraph.textContent = "- " + comment; 122 | commentsElement.appendChild(paragraph); 123 | pageIterator++ 124 | if(pageIterator >= maxMsgPerPage) 125 | { 126 | break 127 | } 128 | } 129 | document.getElementById("contract_state").textContent = contract_state; 130 | } 131 | 132 | const onWalletConnectedCallback = async () => { 133 | } 134 | 135 | document.addEventListener('DOMContentLoaded', async () => { 136 | loadDapp() 137 | }); 138 | 139 | function splitIntoPairs(str) { 140 | return str.match(/.{1,2}/g) || []; 141 | } 142 | 143 | const sendProof = async (comment) => { 144 | document.getElementById("web3_message").textContent="Please sign the message ✍️"; 145 | 146 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 147 | await provider.send("eth_requestAccounts", []); 148 | const signer = provider.getSigner(); 149 | const signderAddress = await signer.getAddress(); 150 | 151 | const signature = await signer.signMessage(comment); 152 | var hashedMessage = ethers.utils.hashMessage(comment) 153 | var publicKey = ethers.utils.recoverPublicKey( 154 | hashedMessage, 155 | signature) 156 | 157 | publicKey = publicKey.substring(4) 158 | 159 | let pub_key_x = publicKey.substring(0, 64); 160 | let pub_key_y = publicKey.substring(64); 161 | 162 | var sSignature = Array.from(ethers.utils.arrayify(signature)) 163 | sSignature.pop() 164 | 165 | const backend = new BarretenbergBackend(circuit); 166 | const noir = new Noir(circuit, backend); 167 | 168 | let merkleTree = [ 169 | { 170 | value: "0x707e55a12557E89915D121932F83dEeEf09E5d70", 171 | index: "0", 172 | hashPath: ["0x000000000000000000000000bef34f2FCAe62dC3404c3d01AF65a7784c9c4A19","0x00000000000000000000000008966BfFa14A7d0d7751355C84273Bb2eaF20FC3"], 173 | }, 174 | { 175 | value: "0xbef34f2FCAe62dC3404c3d01AF65a7784c9c4A19", 176 | index: "1", 177 | hashPath: ["0x000000000000000000000000707e55a12557E89915D121932F83dEeEf09E5d70","0x00000000000000000000000008966BfFa14A7d0d7751355C84273Bb2eaF20FC3"], 178 | }, 179 | { 180 | value: "0x08966BfFa14A7d0d7751355C84273Bb2eaF20FC3", 181 | index: "2", 182 | hashPath: ["0x00000000000000000000000008966BfFa14A7d0d7751355C84273Bb2eaF20FC3","0x1476e5c502f3a532e7c36640e88eebf769ae99d6c50f3be65279ca937b795a3d"], 183 | } 184 | ] 185 | 186 | let index = null 187 | let hashPath = null 188 | for(let i=0; i { 242 | console.log("ERROR! Transaction reverted: " + revertReason.receipt.transactionHash) 243 | }); 244 | */ 245 | 246 | 247 | } 248 | 249 | const updateMetadata = async (proof, hashedMessage, comment) => { 250 | fetch(METADA_API_URL + "/relay?proof=" + proof + "&hashedMessage=" + hashedMessage + "&comment=" + comment) 251 | .then(res => res.json()) 252 | .then(out => 253 | console.log(out)) 254 | .catch(); 255 | } 256 | 257 | 258 | window.sendProof=sendProof; -------------------------------------------------------------------------------- /circuit/target/debug_circuit.json: -------------------------------------------------------------------------------- 1 | {"debug_symbols":[{"locations":{"160":[{"span":{"start":420,"end":485},"file":0}],"161":[{"span":{"start":498,"end":513},"file":0}],"162":[{"span":{"start":660,"end":680},"file":0},{"span":{"start":1282,"end":1349},"file":2}],"163":[{"span":{"start":660,"end":680},"file":0},{"span":{"start":1380,"end":1413},"file":2}],"164":[{"span":{"start":660,"end":680},"file":0},{"span":{"start":1380,"end":1413},"file":2}],"165":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":529,"end":555},"file":28},{"span":{"start":122,"end":149},"file":18}],"166":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":529,"end":555},"file":28},{"span":{"start":122,"end":149},"file":18}],"167":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":529,"end":555},"file":28},{"span":{"start":122,"end":149},"file":18}],"168":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":529,"end":555},"file":28},{"span":{"start":122,"end":149},"file":18}],"169":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"170":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"171":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"172":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"173":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"174":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"175":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"176":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"177":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"178":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"179":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"180":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"181":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"182":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"183":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"184":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"185":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"186":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"187":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"188":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"189":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"190":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"191":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"192":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"193":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"194":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"195":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"196":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":716,"end":728},"file":28}],"197":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"198":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"199":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"200":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"201":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"202":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"203":[{"span":{"start":761,"end":817},"file":0},{"span":{"start":821,"end":872},"file":28},{"span":{"start":755,"end":793},"file":26}],"204":[{"span":{"start":832,"end":852},"file":0}],"162.13":[{"span":{"start":2647,"end":2648},"file":3}],"162.14":[{"span":{"start":2647,"end":2648},"file":3}],"162.15":[{"span":{"start":2647,"end":2648},"file":3}],"162.16":[{"span":{"start":2647,"end":2648},"file":3}],"162.17":[{"span":{"start":2647,"end":2648},"file":3}],"162.18":[{"span":{"start":2647,"end":2648},"file":3}],"162.19":[{"span":{"start":2647,"end":2648},"file":3}],"162.20":[{"span":{"start":2647,"end":2648},"file":3}],"162.21":[{"span":{"start":2647,"end":2648},"file":3}],"162.22":[{"span":{"start":2647,"end":2648},"file":3}],"162.23":[{"span":{"start":2647,"end":2648},"file":3}],"162.24":[{"span":{"start":2647,"end":2648},"file":3}],"162.25":[{"span":{"start":2647,"end":2648},"file":3}],"162.26":[{"span":{"start":2647,"end":2648},"file":3}],"162.27":[{"span":{"start":2647,"end":2648},"file":3}],"162.28":[{"span":{"start":2647,"end":2648},"file":3}],"162.29":[{"span":{"start":2647,"end":2648},"file":3}],"162.30":[{"span":{"start":2647,"end":2648},"file":3}],"162.31":[{"span":{"start":2647,"end":2648},"file":3}],"162.32":[{"span":{"start":2647,"end":2648},"file":3}],"162.33":[{"span":{"start":2647,"end":2648},"file":3}],"162.34":[{"span":{"start":2647,"end":2648},"file":3}],"162.35":[{"span":{"start":2647,"end":2648},"file":3}],"162.36":[{"span":{"start":2647,"end":2648},"file":3}],"162.37":[{"span":{"start":2647,"end":2648},"file":3}],"162.38":[{"span":{"start":2647,"end":2648},"file":3}],"162.39":[{"span":{"start":2647,"end":2648},"file":3}],"162.40":[{"span":{"start":2647,"end":2648},"file":3}],"162.41":[{"span":{"start":2647,"end":2648},"file":3}],"162.42":[{"span":{"start":2647,"end":2648},"file":3}],"162.43":[{"span":{"start":2647,"end":2648},"file":3}],"162.44":[{"span":{"start":2647,"end":2648},"file":3}],"162.45":[{"span":{"start":2647,"end":2648},"file":3}],"162.46":[{"span":{"start":2647,"end":2648},"file":3}],"162.47":[{"span":{"start":2647,"end":2648},"file":3}],"162.48":[{"span":{"start":2647,"end":2648},"file":3}],"162.49":[{"span":{"start":2647,"end":2648},"file":3}],"162.50":[{"span":{"start":2647,"end":2648},"file":3}],"162.51":[{"span":{"start":2647,"end":2648},"file":3}],"162.52":[{"span":{"start":2647,"end":2648},"file":3}],"162.53":[{"span":{"start":2647,"end":2648},"file":3}],"162.54":[{"span":{"start":2647,"end":2648},"file":3}],"162.55":[{"span":{"start":2647,"end":2648},"file":3}],"162.56":[{"span":{"start":2647,"end":2648},"file":3}],"162.57":[{"span":{"start":2647,"end":2648},"file":3}],"162.58":[{"span":{"start":2647,"end":2648},"file":3}],"162.59":[{"span":{"start":2647,"end":2648},"file":3}],"162.60":[{"span":{"start":2647,"end":2648},"file":3}],"162.61":[{"span":{"start":2647,"end":2648},"file":3}],"162.62":[{"span":{"start":2647,"end":2648},"file":3}],"162.63":[{"span":{"start":2647,"end":2648},"file":3}],"162.64":[{"span":{"start":2647,"end":2648},"file":3}],"162.65":[{"span":{"start":2647,"end":2648},"file":3}],"162.66":[{"span":{"start":2647,"end":2648},"file":3}],"162.67":[{"span":{"start":2647,"end":2648},"file":3}],"162.68":[{"span":{"start":2647,"end":2648},"file":3}],"162.69":[{"span":{"start":2647,"end":2648},"file":3}],"162.70":[{"span":{"start":2647,"end":2648},"file":3}],"162.71":[{"span":{"start":2647,"end":2648},"file":3}],"162.72":[{"span":{"start":2647,"end":2648},"file":3}],"162.73":[{"span":{"start":2647,"end":2648},"file":3}],"162.74":[{"span":{"start":2647,"end":2648},"file":3}],"162.75":[{"span":{"start":2647,"end":2648},"file":3}],"162.76":[{"span":{"start":2647,"end":2648},"file":3}],"162.77":[{"span":{"start":2647,"end":2648},"file":3}],"162.78":[{"span":{"start":2647,"end":2648},"file":3}],"162.79":[{"span":{"start":2647,"end":2648},"file":3}],"162.80":[{"span":{"start":2647,"end":2648},"file":3}],"162.81":[{"span":{"start":2647,"end":2648},"file":3}],"162.82":[{"span":{"start":2647,"end":2648},"file":3}],"162.83":[{"span":{"start":2647,"end":2648},"file":3}],"162.84":[{"span":{"start":2647,"end":2648},"file":3}],"162.85":[{"span":{"start":2647,"end":2648},"file":3}],"162.86":[{"span":{"start":2647,"end":2648},"file":3}],"162.87":[{"span":{"start":2647,"end":2648},"file":3}],"162.88":[{"span":{"start":2647,"end":2648},"file":3}],"162.89":[{"span":{"start":2647,"end":2648},"file":3}],"162.90":[{"span":{"start":2647,"end":2648},"file":3}],"162.91":[{"span":{"start":2647,"end":2648},"file":3}],"162.92":[{"span":{"start":2647,"end":2648},"file":3}],"162.93":[{"span":{"start":2647,"end":2648},"file":3}],"162.94":[{"span":{"start":2647,"end":2648},"file":3}],"162.95":[{"span":{"start":2647,"end":2648},"file":3}],"162.96":[{"span":{"start":2647,"end":2648},"file":3}],"162.97":[{"span":{"start":2647,"end":2648},"file":3}],"162.98":[{"span":{"start":2647,"end":2648},"file":3}],"162.99":[{"span":{"start":2647,"end":2648},"file":3}],"162.100":[{"span":{"start":2647,"end":2648},"file":3}],"162.101":[{"span":{"start":2647,"end":2648},"file":3}],"162.102":[{"span":{"start":2647,"end":2648},"file":3}],"162.103":[{"span":{"start":2647,"end":2648},"file":3}],"162.104":[{"span":{"start":2647,"end":2648},"file":3}],"162.105":[{"span":{"start":2647,"end":2648},"file":3}],"162.106":[{"span":{"start":2647,"end":2648},"file":3}],"162.107":[{"span":{"start":2647,"end":2648},"file":3}],"162.108":[{"span":{"start":2647,"end":2648},"file":3}],"162.109":[{"span":{"start":2647,"end":2648},"file":3}],"162.110":[{"span":{"start":2647,"end":2648},"file":3}],"162.111":[{"span":{"start":2647,"end":2648},"file":3}],"162.112":[{"span":{"start":2647,"end":2648},"file":3}],"162.113":[{"span":{"start":2647,"end":2648},"file":3}],"162.114":[{"span":{"start":2647,"end":2648},"file":3}],"162.115":[{"span":{"start":2647,"end":2648},"file":3}],"162.116":[{"span":{"start":2647,"end":2648},"file":3}],"162.117":[{"span":{"start":2647,"end":2648},"file":3}],"162.118":[{"span":{"start":2647,"end":2648},"file":3}],"162.119":[{"span":{"start":2647,"end":2648},"file":3}],"162.120":[{"span":{"start":2647,"end":2648},"file":3}],"162.121":[{"span":{"start":2647,"end":2648},"file":3}],"162.122":[{"span":{"start":2647,"end":2648},"file":3}],"162.123":[{"span":{"start":2647,"end":2648},"file":3}],"162.124":[{"span":{"start":2647,"end":2648},"file":3}],"162.125":[{"span":{"start":2647,"end":2648},"file":3}],"162.126":[{"span":{"start":2647,"end":2648},"file":3}],"162.127":[{"span":{"start":2647,"end":2648},"file":3}],"162.128":[{"span":{"start":2647,"end":2648},"file":3}],"162.129":[{"span":{"start":2647,"end":2648},"file":3}],"162.130":[{"span":{"start":2647,"end":2648},"file":3}],"162.131":[{"span":{"start":2647,"end":2648},"file":3}],"162.132":[{"span":{"start":2647,"end":2648},"file":3}],"162.133":[{"span":{"start":2647,"end":2648},"file":3}],"162.134":[{"span":{"start":2647,"end":2648},"file":3}],"162.135":[{"span":{"start":2647,"end":2648},"file":3}],"162.136":[{"span":{"start":2647,"end":2648},"file":3}],"162.137":[{"span":{"start":2647,"end":2648},"file":3}],"162.138":[{"span":{"start":2647,"end":2648},"file":3}],"162.139":[{"span":{"start":2647,"end":2648},"file":3}],"162.140":[{"span":{"start":2647,"end":2648},"file":3}],"162.141":[{"span":{"start":2647,"end":2648},"file":3}],"162.142":[{"span":{"start":2647,"end":2648},"file":3}],"162.143":[{"span":{"start":2647,"end":2648},"file":3}],"162.144":[{"span":{"start":2647,"end":2648},"file":3}],"162.145":[{"span":{"start":2647,"end":2648},"file":3}],"162.146":[{"span":{"start":2647,"end":2648},"file":3}],"162.147":[{"span":{"start":2647,"end":2648},"file":3}],"162.148":[{"span":{"start":2647,"end":2648},"file":3}],"162.149":[{"span":{"start":2647,"end":2648},"file":3}],"162.150":[{"span":{"start":2647,"end":2648},"file":3}],"162.151":[{"span":{"start":2647,"end":2648},"file":3}],"162.152":[{"span":{"start":2647,"end":2648},"file":3}],"162.153":[{"span":{"start":2647,"end":2648},"file":3}],"162.154":[{"span":{"start":2647,"end":2648},"file":3}],"162.155":[{"span":{"start":2647,"end":2648},"file":3}],"162.156":[{"span":{"start":2647,"end":2648},"file":3}],"162.157":[{"span":{"start":2647,"end":2648},"file":3}],"162.158":[{"span":{"start":2647,"end":2648},"file":3}],"162.159":[{"span":{"start":2647,"end":2648},"file":3}],"162.160":[{"span":{"start":2647,"end":2648},"file":3}],"162.161":[{"span":{"start":2647,"end":2648},"file":3}],"162.162":[{"span":{"start":2647,"end":2648},"file":3}],"162.163":[{"span":{"start":2647,"end":2648},"file":3}],"162.164":[{"span":{"start":2647,"end":2648},"file":3}],"162.165":[{"span":{"start":2647,"end":2648},"file":3}],"162.166":[{"span":{"start":2647,"end":2648},"file":3}],"162.167":[{"span":{"start":2647,"end":2648},"file":3}],"162.168":[{"span":{"start":2647,"end":2648},"file":3}],"162.169":[{"span":{"start":2647,"end":2648},"file":3}],"162.170":[{"span":{"start":2647,"end":2648},"file":3}],"162.171":[{"span":{"start":2647,"end":2648},"file":3}],"162.172":[{"span":{"start":2647,"end":2648},"file":3}],"162.173":[{"span":{"start":2647,"end":2648},"file":3}],"162.174":[{"span":{"start":2647,"end":2648},"file":3}],"162.175":[{"span":{"start":2647,"end":2648},"file":3}],"162.176":[{"span":{"start":2647,"end":2648},"file":3}],"162.177":[{"span":{"start":2647,"end":2648},"file":3}],"162.178":[{"span":{"start":2647,"end":2648},"file":3}],"162.179":[{"span":{"start":2647,"end":2648},"file":3}],"162.180":[{"span":{"start":2647,"end":2648},"file":3}],"162.181":[{"span":{"start":2647,"end":2648},"file":3}],"162.182":[{"span":{"start":2647,"end":2648},"file":3}],"162.183":[{"span":{"start":2647,"end":2648},"file":3}],"162.184":[{"span":{"start":2647,"end":2648},"file":3}],"162.185":[{"span":{"start":2647,"end":2648},"file":3}],"162.186":[{"span":{"start":2647,"end":2648},"file":3}],"162.187":[{"span":{"start":2647,"end":2648},"file":3}],"162.188":[{"span":{"start":2647,"end":2648},"file":3}],"162.189":[{"span":{"start":2647,"end":2648},"file":3}],"162.190":[{"span":{"start":2647,"end":2648},"file":3}],"162.191":[{"span":{"start":2647,"end":2648},"file":3}],"162.192":[{"span":{"start":2647,"end":2648},"file":3}],"162.193":[{"span":{"start":2647,"end":2648},"file":3}],"162.194":[{"span":{"start":2647,"end":2648},"file":3}],"162.195":[{"span":{"start":2647,"end":2648},"file":3}],"162.196":[{"span":{"start":2647,"end":2648},"file":3}],"162.197":[{"span":{"start":2647,"end":2648},"file":3}],"162.198":[{"span":{"start":2647,"end":2648},"file":3}],"162.199":[{"span":{"start":2647,"end":2648},"file":3}],"162.200":[{"span":{"start":2647,"end":2648},"file":3}],"162.201":[{"span":{"start":2647,"end":2648},"file":3}],"162.202":[{"span":{"start":2647,"end":2648},"file":3}],"162.203":[{"span":{"start":2647,"end":2648},"file":3}],"162.204":[{"span":{"start":2647,"end":2648},"file":3}],"162.205":[{"span":{"start":2647,"end":2648},"file":3}],"162.206":[{"span":{"start":2647,"end":2648},"file":3}],"162.207":[{"span":{"start":2647,"end":2648},"file":3}],"162.208":[{"span":{"start":2647,"end":2648},"file":3}],"162.209":[{"span":{"start":2647,"end":2648},"file":3}],"162.210":[{"span":{"start":2647,"end":2648},"file":3}],"162.211":[{"span":{"start":2647,"end":2648},"file":3}],"162.212":[{"span":{"start":2647,"end":2648},"file":3}],"162.213":[{"span":{"start":2647,"end":2648},"file":3}],"162.214":[{"span":{"start":2647,"end":2648},"file":3}],"162.215":[{"span":{"start":2647,"end":2648},"file":3}],"162.216":[{"span":{"start":2647,"end":2648},"file":3}],"162.217":[{"span":{"start":2647,"end":2648},"file":3}],"162.218":[{"span":{"start":2647,"end":2648},"file":3}],"162.219":[{"span":{"start":2647,"end":2648},"file":3}],"162.220":[{"span":{"start":2647,"end":2648},"file":3}],"162.221":[{"span":{"start":2647,"end":2648},"file":3}],"162.222":[{"span":{"start":2647,"end":2648},"file":3}],"162.223":[{"span":{"start":2647,"end":2648},"file":3}],"162.224":[{"span":{"start":2647,"end":2648},"file":3}],"162.225":[{"span":{"start":2647,"end":2648},"file":3}],"162.226":[{"span":{"start":2647,"end":2648},"file":3}],"162.227":[{"span":{"start":2647,"end":2648},"file":3}],"162.228":[{"span":{"start":2647,"end":2648},"file":3}],"162.229":[{"span":{"start":2647,"end":2648},"file":3}],"162.230":[{"span":{"start":2647,"end":2648},"file":3}],"162.231":[{"span":{"start":2647,"end":2648},"file":3}],"162.232":[{"span":{"start":2647,"end":2648},"file":3}],"162.233":[{"span":{"start":2647,"end":2648},"file":3}],"162.234":[{"span":{"start":2647,"end":2648},"file":3}],"162.235":[{"span":{"start":2647,"end":2648},"file":3}],"162.236":[{"span":{"start":2647,"end":2648},"file":3}],"162.237":[{"span":{"start":2647,"end":2648},"file":3}],"162.238":[{"span":{"start":2647,"end":2648},"file":3}],"162.239":[{"span":{"start":2647,"end":2648},"file":3}],"162.240":[{"span":{"start":2647,"end":2648},"file":3}],"162.241":[{"span":{"start":2647,"end":2648},"file":3}],"162.242":[{"span":{"start":2647,"end":2648},"file":3}],"162.243":[{"span":{"start":2647,"end":2648},"file":3}],"162.244":[{"span":{"start":2647,"end":2648},"file":3}],"162.245":[{"span":{"start":2647,"end":2648},"file":3}],"162.246":[{"span":{"start":2647,"end":2648},"file":3}],"162.247":[{"span":{"start":2647,"end":2648},"file":3}],"162.248":[{"span":{"start":2647,"end":2648},"file":3}],"162.249":[{"span":{"start":2647,"end":2648},"file":3}],"162.250":[{"span":{"start":2647,"end":2648},"file":3}],"162.251":[{"span":{"start":2647,"end":2648},"file":3}],"162.252":[{"span":{"start":2647,"end":2648},"file":3}],"162.253":[{"span":{"start":2647,"end":2648},"file":3}],"162.254":[{"span":{"start":2647,"end":2648},"file":3}],"162.255":[{"span":{"start":2647,"end":2648},"file":3}],"162.256":[{"span":{"start":2647,"end":2648},"file":3}],"162.257":[{"span":{"start":2647,"end":2648},"file":3}],"162.258":[{"span":{"start":2647,"end":2648},"file":3}],"162.259":[{"span":{"start":2647,"end":2648},"file":3}],"162.260":[{"span":{"start":2647,"end":2648},"file":3}],"162.261":[{"span":{"start":2647,"end":2648},"file":3}],"162.262":[{"span":{"start":2647,"end":2648},"file":3}],"162.263":[{"span":{"start":2647,"end":2648},"file":3}],"162.264":[{"span":{"start":2647,"end":2648},"file":3}],"162.265":[{"span":{"start":2647,"end":2648},"file":3}],"162.266":[{"span":{"start":2647,"end":2648},"file":3}],"162.267":[{"span":{"start":2647,"end":2648},"file":3}],"162.268":[{"span":{"start":2647,"end":2648},"file":3}],"162.269":[{"span":{"start":2647,"end":2648},"file":3}],"162.270":[{"span":{"start":2647,"end":2648},"file":3}],"162.271":[{"span":{"start":2647,"end":2648},"file":3}],"162.272":[{"span":{"start":2647,"end":2648},"file":3}],"162.273":[{"span":{"start":2647,"end":2648},"file":3}],"162.274":[{"span":{"start":2647,"end":2648},"file":3}],"162.275":[{"span":{"start":2647,"end":2648},"file":3}],"162.276":[{"span":{"start":2647,"end":2648},"file":3}],"162.277":[{"span":{"start":2647,"end":2648},"file":3}],"162.278":[{"span":{"start":2647,"end":2648},"file":3}],"162.279":[{"span":{"start":2647,"end":2648},"file":3}],"162.280":[{"span":{"start":2647,"end":2648},"file":3}],"162.281":[{"span":{"start":2647,"end":2648},"file":3}],"162.282":[{"span":{"start":2647,"end":2648},"file":3}],"162.286":[{"span":{"start":2672,"end":2674},"file":3}],"162.287":[{"span":{"start":2672,"end":2674},"file":3}],"162.293":[{"span":{"start":2731,"end":2733},"file":3}],"162.294":[{"span":{"start":2731,"end":2733},"file":3}],"162.297":[{"span":{"start":2753,"end":2759},"file":3}],"162.298":[{"span":{"start":2753,"end":2759},"file":3}],"162.299":[{"span":{"start":2753,"end":2759},"file":3}],"162.300":[{"span":{"start":2753,"end":2759},"file":3}],"162.301":[{"span":{"start":2753,"end":2759},"file":3}],"162.307":[{"span":{"start":2731,"end":2733},"file":3}],"162.308":[{"span":{"start":2731,"end":2733},"file":3}],"162.309":[{"span":{"start":2731,"end":2733},"file":3}],"162.310":[{"span":{"start":2731,"end":2733},"file":3}],"162.311":[{"span":{"start":2731,"end":2733},"file":3}],"162.312":[{"span":{"start":2753,"end":2759},"file":3}],"162.313":[{"span":{"start":2753,"end":2759},"file":3}],"162.314":[{"span":{"start":2753,"end":2759},"file":3}],"162.315":[{"span":{"start":2753,"end":2759},"file":3}],"162.316":[{"span":{"start":2753,"end":2759},"file":3}],"162.317":[{"span":{"start":2753,"end":2759},"file":3}],"162.318":[{"span":{"start":2763,"end":2771},"file":3}],"162.319":[{"span":{"start":2763,"end":2771},"file":3}],"162.320":[{"span":{"start":2753,"end":2759},"file":3}],"162.321":[{"span":{"start":2753,"end":2759},"file":3}],"162.322":[{"span":{"start":2753,"end":2759},"file":3}],"162.323":[{"span":{"start":2753,"end":2759},"file":3}],"162.324":[{"span":{"start":2753,"end":2759},"file":3}],"162.325":[{"span":{"start":2753,"end":2759},"file":3}],"162.326":[{"span":{"start":2753,"end":2759},"file":3}],"162.327":[{"span":{"start":2753,"end":2759},"file":3}],"162.328":[{"span":{"start":2753,"end":2759},"file":3}],"162.329":[{"span":{"start":2753,"end":2759},"file":3}],"162.330":[{"span":{"start":2753,"end":2759},"file":3}],"162.331":[{"span":{"start":2753,"end":2759},"file":3}],"162.332":[{"span":{"start":2753,"end":2759},"file":3}],"162.333":[{"span":{"start":2753,"end":2759},"file":3}],"162.334":[{"span":{"start":2753,"end":2759},"file":3}],"162.335":[{"span":{"start":2753,"end":2759},"file":3}],"162.336":[{"span":{"start":2753,"end":2759},"file":3}],"162.337":[{"span":{"start":2753,"end":2759},"file":3}],"162.338":[{"span":{"start":2753,"end":2759},"file":3}],"162.339":[{"span":{"start":2753,"end":2759},"file":3}],"162.340":[{"span":{"start":2753,"end":2759},"file":3}],"162.341":[{"span":{"start":2753,"end":2759},"file":3}],"162.342":[{"span":{"start":2753,"end":2759},"file":3}],"162.343":[{"span":{"start":2753,"end":2759},"file":3}],"162.344":[{"span":{"start":2753,"end":2759},"file":3}],"162.345":[{"span":{"start":2753,"end":2759},"file":3}],"162.346":[{"span":{"start":2753,"end":2759},"file":3}],"162.347":[{"span":{"start":2753,"end":2759},"file":3}],"162.348":[{"span":{"start":2753,"end":2759},"file":3}],"162.349":[{"span":{"start":2753,"end":2759},"file":3}],"162.350":[{"span":{"start":2753,"end":2759},"file":3}],"162.351":[{"span":{"start":2753,"end":2759},"file":3}],"162.354":[{"span":{"start":2672,"end":2674},"file":3}],"162.355":[{"span":{"start":2672,"end":2674},"file":3}],"162.356":[{"span":{"start":2672,"end":2674},"file":3}],"162.357":[{"span":{"start":2672,"end":2674},"file":3}],"162.358":[{"span":{"start":2672,"end":2674},"file":3}],"162.359":[{"span":{"start":2699,"end":2707},"file":3}],"162.360":[{"span":{"start":2699,"end":2707},"file":3}],"162.361":[{"span":{"start":2694,"end":2695},"file":3}],"162.362":[{"span":{"start":2694,"end":2695},"file":3}],"162.363":[{"span":{"start":2694,"end":2695},"file":3}],"162.364":[{"span":{"start":2694,"end":2695},"file":3}],"162.365":[{"span":{"start":2694,"end":2695},"file":3}],"162.366":[{"span":{"start":2694,"end":2695},"file":3}],"162.367":[{"span":{"start":2694,"end":2695},"file":3}],"162.368":[{"span":{"start":2694,"end":2695},"file":3}],"162.369":[{"span":{"start":2694,"end":2695},"file":3}],"162.370":[{"span":{"start":2694,"end":2695},"file":3}],"162.371":[{"span":{"start":2694,"end":2695},"file":3}],"162.372":[{"span":{"start":2694,"end":2695},"file":3}],"162.373":[{"span":{"start":2694,"end":2695},"file":3}],"162.374":[{"span":{"start":2694,"end":2695},"file":3}],"162.375":[{"span":{"start":2694,"end":2695},"file":3}],"162.376":[{"span":{"start":2694,"end":2695},"file":3}],"162.377":[{"span":{"start":2694,"end":2695},"file":3}],"162.378":[{"span":{"start":2694,"end":2695},"file":3}],"162.379":[{"span":{"start":2694,"end":2695},"file":3}],"162.380":[{"span":{"start":2694,"end":2695},"file":3}],"162.381":[{"span":{"start":2694,"end":2695},"file":3}],"162.382":[{"span":{"start":2694,"end":2695},"file":3}],"162.383":[{"span":{"start":2694,"end":2695},"file":3}],"162.384":[{"span":{"start":2694,"end":2695},"file":3}],"162.385":[{"span":{"start":2694,"end":2695},"file":3}],"162.386":[{"span":{"start":2694,"end":2695},"file":3}],"162.387":[{"span":{"start":2694,"end":2695},"file":3}],"162.388":[{"span":{"start":2694,"end":2695},"file":3}],"162.389":[{"span":{"start":2694,"end":2695},"file":3}],"162.390":[{"span":{"start":2694,"end":2695},"file":3}],"162.391":[{"span":{"start":2694,"end":2695},"file":3}],"162.392":[{"span":{"start":2694,"end":2695},"file":3}]}}],"file_map":{"0":{"source":"use dep::std::ecdsa_secp256k1::verify_signature;\nuse dep::std;\nuse dep::std::scalar_mul;\nuse dep::std::hash;\nuse dep::ecrecover;\n\nfn main(\n pub_key_x: [u8; 32],\n pub_key_y: [u8; 32],\n signature: [u8; 64],\n hashed_message: pub [u8; 32],\n root: pub Field,\n index: Field,\n hash_path: [Field; 2]\n) {\n // First, let's check if signature is vaild and corresponds to the public key provided\n let valid_signature = verify_signature(pub_key_x, pub_key_y, signature, hashed_message);\n assert(valid_signature);\n\n // Grab the ethereum address from the public key\n let key = ecrecover::secp256k1::PubKey::from_xy(pub_key_x, pub_key_y);\n let leaf = key.to_eth_address();\n\n // Check if the address is part of the merkle tree\n let computedRoot = std::merkle::compute_merkle_root(leaf, index, hash_path);\n\n assert (root == computedRoot);\n}","path":"/home/turupawn/Projects/EcrecoverInclusionProof/circuit/src/main.nr"},"2":{"source":"use dep::std;\n\nuse dep::array_helpers;\n\nstruct PubKey {\n pub_x: [u8; 32],\n pub_y: [u8; 32],\n}\n\nunconstrained\nfn split_uncompressed_pub_key(\n pub_key: [u8; 65]\n) -> ([u8; 32], [u8; 32]) {\n let mut pub_key_x: [u8; 32] = [0; 32];\n let mut pub_key_y: [u8; 32] = [0; 32];\n\n for i in 0..32 {\n pub_key_x[i] = pub_key[i + 1];\n pub_key_y[i] = pub_key[i + 32 + 1];\n };\n\n (pub_key_x, pub_key_y)\n}\n\nimpl PubKey {\n fn from_xy(pub_x: [u8; 32], pub_y: [u8; 32]) -> PubKey {\n PubKey {\n pub_x,\n pub_y,\n }\n }\n\n fn from_unified(pub_key: [u8; 64]) -> PubKey {\n let (key_x, key_y) = array_helpers::split_u8_64_unconstrained(pub_key);\n\n PubKey {\n pub_x: key_x,\n pub_y: key_y,\n }\n }\n\n fn from_uncompressed(pub_key: [u8; 65]) -> PubKey {\n assert(pub_key[0] == 0x04);\n let (key_x, key_y) = split_uncompressed_pub_key(pub_key);\n\n PubKey {\n pub_x: key_x,\n pub_y: key_y,\n }\n }\n\n fn verify_sig(self, signature: [u8; 64], hashed_message: [u8; 32]) -> bool {\n std::ecdsa_secp256k1::verify_signature(self.pub_x, self.pub_y, signature, hashed_message)\n }\n\n fn to_eth_address(self) -> Field {\n let pub_key = array_helpers::u8_32_to_u8_64_unconstrained(self.pub_x, self.pub_y);\n let hashed_pub_key = std::hash::keccak256(pub_key, 64);\n\n let mut addr: Field = 0;\n for i in 0..20 {\n // shift left by 8 and add the new value\n addr = (addr * 256) + hashed_pub_key[i + 12] as Field;\n }\n\n addr\n }\n\n fn ecrecover(\n self,\n signature: [u8; 64],\n hashed_message: [u8; 32]\n ) -> Field {\n assert(self.verify_sig(signature, hashed_message));\n\n self.to_eth_address()\n }\n}\n\n\n#[test]\nfn test_ecrecover_via_key() {\n let pub_key_x = [131, 24, 83, 91, 84, 16, 93, 74, 122, 174, 96, 192, 143, 196, 95, 150, 135, 24, 27, 79, 223, 198, 37, 189, 26, 117, 63, 167, 57, 127, 237, 117];\n let pub_key_y = [53, 71, 241, 28, 168, 105, 102, 70, 242, 243, 172, 176, 142, 49, 1, 106, 250, 194, 62, 99, 12, 93, 17, 245, 159, 97, 254, 245, 123, 13, 42, 165];\n let signature = [57, 17, 112, 239, 241, 30, 64, 157, 170, 50, 85, 145, 156, 69, 226, 85, 147, 164, 10, 82, 71, 93, 42, 132, 200, 220, 161, 255, 95, 241, 211, 141, 81, 7, 150, 25, 25, 27, 162, 213, 80, 61, 12, 170, 50, 4, 154, 203, 252, 229, 119, 29, 202, 153, 50, 25, 126, 145, 245, 23, 136, 75, 29, 177];\n let hashed_message = [13, 82, 120, 60, 76, 186, 215, 235, 175, 126, 185, 67, 252, 100, 143, 82, 130, 165, 32, 112, 68, 47, 193, 141, 141, 209, 109, 219, 47, 203, 175, 102];\n\n let key = PubKey::from_xy(pub_key_x, pub_key_y);\n assert(key.ecrecover(signature, hashed_message) == 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266);\n}\n","path":"/home/turupawn/nargo/github.com/colinnielsen/ecrecover-noirv0.19.0/src/secp256k1.nr"},"3":{"source":"use dep::std;\n\nfn u8_32s_to_u64_16(\n arr_a: [u8; 32],\n arr_b: [u8; 32],\n) -> [u64; 16] {\n let mut combined_u64: [u64; 16] = [0; 16];\n \n for i in 0..4 {\n let mut value: u64 = 0;\n for j in 0..8 {\n value |= (arr_a[i*8+j] as u64) << ((56 - j*8) as u64);\n }\n combined_u64[i] = value;\n }\n for i in 4..8 {\n let mut value: u64 = 0;\n for j in 0..8 {\n value |= (arr_b[(i-4)*8+j] as u64) << ((56 - j*8) as u64);\n }\n combined_u64[i] = value;\n }\n\n combined_u64\n}\n\nunconstrained\nfn u8_32s_to_u64_16_unconstrained(\n arr_a: [u8; 32],\n arr_b: [u8; 32],\n) -> [u64; 16] {\n let mut combined_u64: [u64; 16] = [0; 16];\n \n for i in 0..4 {\n let mut value: u64 = 0;\n for j in 0..8 {\n value |= (arr_a[i*8+j] as u64) << ((56 - j*8) as u64);\n }\n combined_u64[i] = value;\n }\n for i in 4..8 {\n let mut value: u64 = 0;\n for j in 0..8 {\n value |= (arr_b[(i-4)*8+j] as u64) << ((56 - j*8) as u64);\n }\n combined_u64[i] = value;\n }\n\n combined_u64\n}\n\n#[test]\nfn test_u8_32s_to_u64_16() {\n let arr_a: [u8; 32] = [\n 131,24,83,91,84,16,93,74,122,174,96,192,143,196,95,150,135,24,27,79,223,198,37,189,26,117,63,167,57,127,237,117\n ];\n let arr_b: [u8; 32] = [\n 53,71,241,28,168,105,102,70,242,243,172,176,142,49,1,106,250,194,62,99,12,93,17,245,159,97,254,245,123,13,42,165\n ];\n let out = u8_32s_to_u64_16(arr_a, arr_b);\n\n assert(out[0] == 9446391870127103306);\n assert(out[1] == 8840109498736861078);\n assert(out[2] == 9734560624431998397);\n assert(out[3] == 1906500004718046581);\n assert(out[4] == 3839302312743495238);\n assert(out[5] == 17506526050819047786);\n assert(out[6] == 18069073250093961717);\n assert(out[7] == 11484740855056378533);\n assert(out[8] == 0);\n assert(out[9] == 0);\n assert(out[10] == 0);\n assert(out[11] == 0);\n assert(out[12] == 0);\n assert(out[13] == 0);\n assert(out[14] == 0);\n assert(out[15] == 0);\n // the above output is the hex \"0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5\"\n}\n\nfn u8_32_to_u8_64(\n arr_a: [u8; 32],\n arr_b: [u8; 32],\n) -> [u8; 64] {\n let mut combined: [u8; 64] = [0; 64];\n\n for i in 0..32 {\n combined[i] = arr_a[i];\n }\n for i in 0..32 {\n combined[i + 32] = arr_b[i];\n }\n\n combined\n}\n\nunconstrained\nfn u8_32_to_u8_64_unconstrained(\n arr_a: [u8; 32],\n arr_b: [u8; 32],\n) -> [u8; 64] {\n let mut combined: [u8; 64] = [0; 64];\n\n for i in 0..32 {\n combined[i] = arr_a[i];\n }\n for i in 0..32 {\n combined[i + 32] = arr_b[i];\n }\n\n combined\n}\n\n\nfn u64_4_to_u8_32(\n array: [u64; 4]\n) -> [u8; 32] {\n let mut output: [u8; 32] = [0; 32];\n let mut output_index = 0;\n\n for num_idx in 0..4 {\n for bit_pos in 0..8 {\n let shift_amount: u64 = 56 - (bit_pos * 8) as u64;\n output[output_index] = ((array[num_idx] >> shift_amount) & 255) as u8;\n output_index += 1;\n }\n }\n\n output\n}\n\nunconstrained\nfn u64_4_to_u8_32_unconstrained(\n array: [u64; 4]\n) -> [u8; 32] {\n let mut output: [u8; 32] = [0; 32];\n let mut output_index = 0;\n\n for num_idx in 0..4 {\n for bit_pos in 0..8 {\n let shift_amount: u64 = 56 - (bit_pos * 8) as u64;\n output[output_index] = ((array[num_idx] >> shift_amount) & 255) as u8;\n output_index += 1;\n }\n }\n\n output\n}\n\n#[test]\nfn test_u64_4_to_u8_32() {\n let hash: [u64; 4] = [\n 999647796417551690,\n 8840109498736861078,\n 9734560624431998397,\n 1906500004718046581\n ];\n \n let arr_out = u64_4_to_u8_32(hash);\n\n assert(arr_out[0] == 13);\n assert(arr_out[1] == 223);\n assert(arr_out[2] == 118);\n assert(arr_out[3] == 95);\n assert(arr_out[4] == 221);\n assert(arr_out[5] == 248);\n assert(arr_out[6] == 93);\n assert(arr_out[7] == 74);\n assert(arr_out[8] == 122);\n assert(arr_out[9] == 174);\n assert(arr_out[10] == 96);\n assert(arr_out[11] == 192);\n assert(arr_out[12] == 143);\n assert(arr_out[13] == 196);\n assert(arr_out[14] == 95);\n assert(arr_out[15] == 150);\n assert(arr_out[16] == 135);\n assert(arr_out[17] == 24);\n assert(arr_out[18] == 27);\n assert(arr_out[19] == 79);\n assert(arr_out[20] == 223);\n assert(arr_out[21] == 198);\n assert(arr_out[22] == 37);\n assert(arr_out[23] == 189);\n assert(arr_out[24] == 26);\n assert(arr_out[25] == 117);\n assert(arr_out[26] == 63);\n assert(arr_out[27] == 167);\n assert(arr_out[28] == 57);\n assert(arr_out[29] == 127);\n assert(arr_out[30] == 237);\n assert(arr_out[31] == 117);\n}\n\n/// @dev this method is used to convert a u8 array to a u160 (which is not supported by Noir, so it's represented as a Field)\n/// @dev will throw on Field overflow\nfn u8_to_u160(\n array: [u8]\n) -> Field {\n let mut addr: Field = 0;\n\n for i in 0..20 {\n // only take the last 20 bytes of the hash\n addr = (addr * 256) + (array[i] as Field);\n }\n\n addr\n}\n\nunconstrained\nfn u8_to_u160_unconstrained(\n array: [u8]\n) -> Field {\n let mut addr: Field = 0;\n\n for i in 0..20 {\n // only take the last 20 bytes of the hash\n addr = (addr * 256) + (array[i] as Field);\n }\n\n addr\n}\n\nfn u8_to_eth_address(\n array: [u8]\n) -> Field {\n u8_to_u160(array)\n}\n\nunconstrained\nfn u8_to_eth_address_unconstrained(\n array: [u8]\n) -> Field {\n u8_to_u160(array)\n}\n\n#[test]\nfn test_u8_32_to_u160() {\n // keccak hash of hardhat 0 address pub key (0xc1ffd3cfee2d9e5cd67643f8f39fd6e51aad88f6f4ce6ab8827279cfffb92266) as u8 array\n let hashed_pub_key = [\n 193,255,211,207,238,45,158,92,214,118,67,248,243,159,214,229,26,173,136,246,244,206,106,184,130,114,121,207,255,185,34,102\n ];\n\n let mut right_20_bytes: [u8] = [0; 20];\n for i in 0..20 {\n right_20_bytes[i] = hashed_pub_key[i + 12];\n }\n\n let addr = u8_to_u160(right_20_bytes);\n let addr_aliased = u8_to_eth_address(right_20_bytes);\n\n assert(addr == addr_aliased);\n assert(addr == 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266); // hardhat address 0\n}\n\nfn split_u8_64(\n arr: [u8; 64]\n) -> ([u8; 32], [u8; 32]) {\n let mut arr_a: [u8; 32] = [0; 32];\n let mut arr_b: [u8; 32] = [0; 32];\n\n for i in 0..32 {\n arr_a[i] = arr[i];\n arr_b[i] = arr[i + 32];\n };\n\n (arr_a, arr_b)\n}\n\nunconstrained\nfn split_u8_64_unconstrained(\n arr: [u8; 64]\n) -> ([u8; 32], [u8; 32]) {\n let mut arr_a: [u8; 32] = [0; 32];\n let mut arr_b: [u8; 32] = [0; 32];\n\n for i in 0..32 {\n arr_a[i] = arr[i];\n arr_b[i] = arr[i + 32];\n };\n\n (arr_a, arr_b)\n}\n\n#[test]\nfn test_split_u8_64() {\n let u8_64 = [\n 193,255,211,207,238,45,158,92,214,118,67,248,243,159,214,229,26,173,136,246,244,206,106,184,130,114,121,207,255,185,34,102,\n 193,255,211,207,238,45,158,92,214,118,67,248,243,159,214,229,26,173,136,246,244,206,106,184,130,114,121,207,255,185,34,102\n ];\n\n let (arr_a, arr_b) = split_u8_64(u8_64);\n\n for i in 0..32 {\n assert(arr_a[i] == u8_64[i]);\n assert(arr_b[i] == u8_64[i + 32]);\n }\n}\n","path":"/home/turupawn/nargo/github.com/colinnielsen/noir-array-helpersv0.19.0/src/lib.nr"},"18":{"source":"impl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n \n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(_self: Self, _bit_size: u32) -> [u1] {}\n \n #[builtin(to_be_bits)]\n fn __to_be_bits(_self: Self, _bit_size: u32) -> [u1] {}\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(_self: Self, _radix: u32, _result_len: u32) -> [u8] {}\n \n #[builtin(to_be_radix)]\n fn __to_be_radix(_self: Self, _radix: u32, _result_len: u32) -> [u8] {}\n\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> Field {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n","path":"std/field.nr"},"26":{"source":"mod poseidon;\nmod mimc;\n\n#[foreign(sha256)]\npub fn sha256(_input: [u8; N]) -> [u8; 32] {}\n\n#[foreign(blake2s)]\npub fn blake2s(_input: [u8; N]) -> [u8; 32] {}\n\nstruct PedersenPoint {\n x : Field,\n y : Field,\n}\n\npub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint {\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(_input: [Field; N], _separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n PedersenPoint { x: values[0], y: values[1] }\n}\n\npub fn pedersen_hash(input: [Field; N]) -> Field {\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(_input: [Field; N], _separator: u32) -> Field {}\n\npub fn hash_to_field(_input: [Field; N]) -> Field {\n let mut inputs_as_bytes = [];\n\n for i in 0..N {\n let input_bytes = _input[i].to_le_bytes(32);\n for i in 0..32 {\n inputs_as_bytes = inputs_as_bytes.push_back(input_bytes[i]);\n }\n }\n\n let hashed_input = blake2s(inputs_as_bytes);\n crate::field::bytes32_to_field(hashed_input)\n}\n\n#[foreign(keccak256)]\npub fn keccak256(_input: [u8; N], _message_size: u32) -> [u8; 32] {}\n\n","path":"std/hash.nr"},"28":{"source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n","path":"std/merkle.nr"}},"warnings":[]} -------------------------------------------------------------------------------- /relayer/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "relayer", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "relayer", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "dotenv": "^10.0.0", 14 | "ethers": "^6.9.0", 15 | "express": "^4.18.2", 16 | "node-fetch": "^3.1.0" 17 | } 18 | }, 19 | "node_modules/@adraffy/ens-normalize": { 20 | "version": "1.10.0", 21 | "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", 22 | "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" 23 | }, 24 | "node_modules/accepts": { 25 | "version": "1.3.8", 26 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 27 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 28 | "dependencies": { 29 | "mime-types": "~2.1.34", 30 | "negotiator": "0.6.3" 31 | }, 32 | "engines": { 33 | "node": ">= 0.6" 34 | } 35 | }, 36 | "node_modules/aes-js": { 37 | "version": "4.0.0-beta.5", 38 | "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", 39 | "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" 40 | }, 41 | "node_modules/array-flatten": { 42 | "version": "1.1.1", 43 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 44 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 45 | }, 46 | "node_modules/body-parser": { 47 | "version": "1.20.1", 48 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 49 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 50 | "dependencies": { 51 | "bytes": "3.1.2", 52 | "content-type": "~1.0.4", 53 | "debug": "2.6.9", 54 | "depd": "2.0.0", 55 | "destroy": "1.2.0", 56 | "http-errors": "2.0.0", 57 | "iconv-lite": "0.4.24", 58 | "on-finished": "2.4.1", 59 | "qs": "6.11.0", 60 | "raw-body": "2.5.1", 61 | "type-is": "~1.6.18", 62 | "unpipe": "1.0.0" 63 | }, 64 | "engines": { 65 | "node": ">= 0.8", 66 | "npm": "1.2.8000 || >= 1.4.16" 67 | } 68 | }, 69 | "node_modules/bufferutil": { 70 | "version": "4.0.8", 71 | "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", 72 | "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", 73 | "hasInstallScript": true, 74 | "optional": true, 75 | "peer": true, 76 | "dependencies": { 77 | "node-gyp-build": "^4.3.0" 78 | }, 79 | "engines": { 80 | "node": ">=6.14.2" 81 | } 82 | }, 83 | "node_modules/bytes": { 84 | "version": "3.1.2", 85 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 86 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 87 | "engines": { 88 | "node": ">= 0.8" 89 | } 90 | }, 91 | "node_modules/call-bind": { 92 | "version": "1.0.5", 93 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", 94 | "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", 95 | "dependencies": { 96 | "function-bind": "^1.1.2", 97 | "get-intrinsic": "^1.2.1", 98 | "set-function-length": "^1.1.1" 99 | }, 100 | "funding": { 101 | "url": "https://github.com/sponsors/ljharb" 102 | } 103 | }, 104 | "node_modules/content-disposition": { 105 | "version": "0.5.4", 106 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 107 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 108 | "dependencies": { 109 | "safe-buffer": "5.2.1" 110 | }, 111 | "engines": { 112 | "node": ">= 0.6" 113 | } 114 | }, 115 | "node_modules/content-type": { 116 | "version": "1.0.5", 117 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 118 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 119 | "engines": { 120 | "node": ">= 0.6" 121 | } 122 | }, 123 | "node_modules/cookie": { 124 | "version": "0.5.0", 125 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 126 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 127 | "engines": { 128 | "node": ">= 0.6" 129 | } 130 | }, 131 | "node_modules/cookie-signature": { 132 | "version": "1.0.6", 133 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 134 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 135 | }, 136 | "node_modules/cors": { 137 | "version": "2.8.5", 138 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 139 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 140 | "dependencies": { 141 | "object-assign": "^4", 142 | "vary": "^1" 143 | }, 144 | "engines": { 145 | "node": ">= 0.10" 146 | } 147 | }, 148 | "node_modules/data-uri-to-buffer": { 149 | "version": "4.0.1", 150 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 151 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", 152 | "engines": { 153 | "node": ">= 12" 154 | } 155 | }, 156 | "node_modules/debug": { 157 | "version": "2.6.9", 158 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 159 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 160 | "dependencies": { 161 | "ms": "2.0.0" 162 | } 163 | }, 164 | "node_modules/define-data-property": { 165 | "version": "1.1.1", 166 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", 167 | "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", 168 | "dependencies": { 169 | "get-intrinsic": "^1.2.1", 170 | "gopd": "^1.0.1", 171 | "has-property-descriptors": "^1.0.0" 172 | }, 173 | "engines": { 174 | "node": ">= 0.4" 175 | } 176 | }, 177 | "node_modules/depd": { 178 | "version": "2.0.0", 179 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 180 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 181 | "engines": { 182 | "node": ">= 0.8" 183 | } 184 | }, 185 | "node_modules/destroy": { 186 | "version": "1.2.0", 187 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 188 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 189 | "engines": { 190 | "node": ">= 0.8", 191 | "npm": "1.2.8000 || >= 1.4.16" 192 | } 193 | }, 194 | "node_modules/dotenv": { 195 | "version": "10.0.0", 196 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", 197 | "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", 198 | "engines": { 199 | "node": ">=10" 200 | } 201 | }, 202 | "node_modules/ee-first": { 203 | "version": "1.1.1", 204 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 205 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 206 | }, 207 | "node_modules/encodeurl": { 208 | "version": "1.0.2", 209 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 210 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 211 | "engines": { 212 | "node": ">= 0.8" 213 | } 214 | }, 215 | "node_modules/escape-html": { 216 | "version": "1.0.3", 217 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 218 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 219 | }, 220 | "node_modules/etag": { 221 | "version": "1.8.1", 222 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 223 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 224 | "engines": { 225 | "node": ">= 0.6" 226 | } 227 | }, 228 | "node_modules/ethers": { 229 | "version": "6.9.0", 230 | "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.9.0.tgz", 231 | "integrity": "sha512-pmfNyQzc2mseLe91FnT2vmNaTt8dDzhxZ/xItAV7uGsF4dI4ek2ufMu3rAkgQETL/TIs0GS5A+U05g9QyWnv3Q==", 232 | "funding": [ 233 | { 234 | "type": "individual", 235 | "url": "https://github.com/sponsors/ethers-io/" 236 | }, 237 | { 238 | "type": "individual", 239 | "url": "https://www.buymeacoffee.com/ricmoo" 240 | } 241 | ], 242 | "dependencies": { 243 | "@adraffy/ens-normalize": "1.10.0", 244 | "@noble/curves": "1.2.0", 245 | "@noble/hashes": "1.3.2", 246 | "@types/node": "18.15.13", 247 | "aes-js": "4.0.0-beta.5", 248 | "tslib": "2.4.0", 249 | "ws": "8.5.0" 250 | }, 251 | "engines": { 252 | "node": ">=14.0.0" 253 | } 254 | }, 255 | "node_modules/ethers/node_modules/@noble/curves": { 256 | "version": "1.2.0", 257 | "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", 258 | "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", 259 | "dependencies": { 260 | "@noble/hashes": "1.3.2" 261 | }, 262 | "funding": { 263 | "url": "https://paulmillr.com/funding/" 264 | } 265 | }, 266 | "node_modules/ethers/node_modules/@noble/hashes": { 267 | "version": "1.3.2", 268 | "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", 269 | "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", 270 | "engines": { 271 | "node": ">= 16" 272 | }, 273 | "funding": { 274 | "url": "https://paulmillr.com/funding/" 275 | } 276 | }, 277 | "node_modules/ethers/node_modules/@types/node": { 278 | "version": "18.15.13", 279 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", 280 | "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" 281 | }, 282 | "node_modules/ethers/node_modules/tslib": { 283 | "version": "2.4.0", 284 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", 285 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" 286 | }, 287 | "node_modules/ethers/node_modules/ws": { 288 | "version": "8.5.0", 289 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", 290 | "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", 291 | "engines": { 292 | "node": ">=10.0.0" 293 | }, 294 | "peerDependencies": { 295 | "bufferutil": "^4.0.1", 296 | "utf-8-validate": "^5.0.2" 297 | }, 298 | "peerDependenciesMeta": { 299 | "bufferutil": { 300 | "optional": true 301 | }, 302 | "utf-8-validate": { 303 | "optional": true 304 | } 305 | } 306 | }, 307 | "node_modules/express": { 308 | "version": "4.18.2", 309 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 310 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 311 | "dependencies": { 312 | "accepts": "~1.3.8", 313 | "array-flatten": "1.1.1", 314 | "body-parser": "1.20.1", 315 | "content-disposition": "0.5.4", 316 | "content-type": "~1.0.4", 317 | "cookie": "0.5.0", 318 | "cookie-signature": "1.0.6", 319 | "debug": "2.6.9", 320 | "depd": "2.0.0", 321 | "encodeurl": "~1.0.2", 322 | "escape-html": "~1.0.3", 323 | "etag": "~1.8.1", 324 | "finalhandler": "1.2.0", 325 | "fresh": "0.5.2", 326 | "http-errors": "2.0.0", 327 | "merge-descriptors": "1.0.1", 328 | "methods": "~1.1.2", 329 | "on-finished": "2.4.1", 330 | "parseurl": "~1.3.3", 331 | "path-to-regexp": "0.1.7", 332 | "proxy-addr": "~2.0.7", 333 | "qs": "6.11.0", 334 | "range-parser": "~1.2.1", 335 | "safe-buffer": "5.2.1", 336 | "send": "0.18.0", 337 | "serve-static": "1.15.0", 338 | "setprototypeof": "1.2.0", 339 | "statuses": "2.0.1", 340 | "type-is": "~1.6.18", 341 | "utils-merge": "1.0.1", 342 | "vary": "~1.1.2" 343 | }, 344 | "engines": { 345 | "node": ">= 0.10.0" 346 | } 347 | }, 348 | "node_modules/fetch-blob": { 349 | "version": "3.2.0", 350 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 351 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 352 | "funding": [ 353 | { 354 | "type": "github", 355 | "url": "https://github.com/sponsors/jimmywarting" 356 | }, 357 | { 358 | "type": "paypal", 359 | "url": "https://paypal.me/jimmywarting" 360 | } 361 | ], 362 | "dependencies": { 363 | "node-domexception": "^1.0.0", 364 | "web-streams-polyfill": "^3.0.3" 365 | }, 366 | "engines": { 367 | "node": "^12.20 || >= 14.13" 368 | } 369 | }, 370 | "node_modules/finalhandler": { 371 | "version": "1.2.0", 372 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 373 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 374 | "dependencies": { 375 | "debug": "2.6.9", 376 | "encodeurl": "~1.0.2", 377 | "escape-html": "~1.0.3", 378 | "on-finished": "2.4.1", 379 | "parseurl": "~1.3.3", 380 | "statuses": "2.0.1", 381 | "unpipe": "~1.0.0" 382 | }, 383 | "engines": { 384 | "node": ">= 0.8" 385 | } 386 | }, 387 | "node_modules/formdata-polyfill": { 388 | "version": "4.0.10", 389 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 390 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 391 | "dependencies": { 392 | "fetch-blob": "^3.1.2" 393 | }, 394 | "engines": { 395 | "node": ">=12.20.0" 396 | } 397 | }, 398 | "node_modules/forwarded": { 399 | "version": "0.2.0", 400 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 401 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 402 | "engines": { 403 | "node": ">= 0.6" 404 | } 405 | }, 406 | "node_modules/fresh": { 407 | "version": "0.5.2", 408 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 409 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 410 | "engines": { 411 | "node": ">= 0.6" 412 | } 413 | }, 414 | "node_modules/function-bind": { 415 | "version": "1.1.2", 416 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 417 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 418 | "funding": { 419 | "url": "https://github.com/sponsors/ljharb" 420 | } 421 | }, 422 | "node_modules/get-intrinsic": { 423 | "version": "1.2.2", 424 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", 425 | "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", 426 | "dependencies": { 427 | "function-bind": "^1.1.2", 428 | "has-proto": "^1.0.1", 429 | "has-symbols": "^1.0.3", 430 | "hasown": "^2.0.0" 431 | }, 432 | "funding": { 433 | "url": "https://github.com/sponsors/ljharb" 434 | } 435 | }, 436 | "node_modules/gopd": { 437 | "version": "1.0.1", 438 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 439 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 440 | "dependencies": { 441 | "get-intrinsic": "^1.1.3" 442 | }, 443 | "funding": { 444 | "url": "https://github.com/sponsors/ljharb" 445 | } 446 | }, 447 | "node_modules/has-property-descriptors": { 448 | "version": "1.0.1", 449 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", 450 | "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", 451 | "dependencies": { 452 | "get-intrinsic": "^1.2.2" 453 | }, 454 | "funding": { 455 | "url": "https://github.com/sponsors/ljharb" 456 | } 457 | }, 458 | "node_modules/has-proto": { 459 | "version": "1.0.1", 460 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 461 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 462 | "engines": { 463 | "node": ">= 0.4" 464 | }, 465 | "funding": { 466 | "url": "https://github.com/sponsors/ljharb" 467 | } 468 | }, 469 | "node_modules/has-symbols": { 470 | "version": "1.0.3", 471 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 472 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 473 | "engines": { 474 | "node": ">= 0.4" 475 | }, 476 | "funding": { 477 | "url": "https://github.com/sponsors/ljharb" 478 | } 479 | }, 480 | "node_modules/hasown": { 481 | "version": "2.0.0", 482 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", 483 | "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", 484 | "dependencies": { 485 | "function-bind": "^1.1.2" 486 | }, 487 | "engines": { 488 | "node": ">= 0.4" 489 | } 490 | }, 491 | "node_modules/http-errors": { 492 | "version": "2.0.0", 493 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 494 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 495 | "dependencies": { 496 | "depd": "2.0.0", 497 | "inherits": "2.0.4", 498 | "setprototypeof": "1.2.0", 499 | "statuses": "2.0.1", 500 | "toidentifier": "1.0.1" 501 | }, 502 | "engines": { 503 | "node": ">= 0.8" 504 | } 505 | }, 506 | "node_modules/iconv-lite": { 507 | "version": "0.4.24", 508 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 509 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 510 | "dependencies": { 511 | "safer-buffer": ">= 2.1.2 < 3" 512 | }, 513 | "engines": { 514 | "node": ">=0.10.0" 515 | } 516 | }, 517 | "node_modules/inherits": { 518 | "version": "2.0.4", 519 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 520 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 521 | }, 522 | "node_modules/ipaddr.js": { 523 | "version": "1.9.1", 524 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 525 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 526 | "engines": { 527 | "node": ">= 0.10" 528 | } 529 | }, 530 | "node_modules/media-typer": { 531 | "version": "0.3.0", 532 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 533 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 534 | "engines": { 535 | "node": ">= 0.6" 536 | } 537 | }, 538 | "node_modules/merge-descriptors": { 539 | "version": "1.0.1", 540 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 541 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 542 | }, 543 | "node_modules/methods": { 544 | "version": "1.1.2", 545 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 546 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 547 | "engines": { 548 | "node": ">= 0.6" 549 | } 550 | }, 551 | "node_modules/mime": { 552 | "version": "1.6.0", 553 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 554 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 555 | "bin": { 556 | "mime": "cli.js" 557 | }, 558 | "engines": { 559 | "node": ">=4" 560 | } 561 | }, 562 | "node_modules/mime-db": { 563 | "version": "1.52.0", 564 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 565 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 566 | "engines": { 567 | "node": ">= 0.6" 568 | } 569 | }, 570 | "node_modules/mime-types": { 571 | "version": "2.1.35", 572 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 573 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 574 | "dependencies": { 575 | "mime-db": "1.52.0" 576 | }, 577 | "engines": { 578 | "node": ">= 0.6" 579 | } 580 | }, 581 | "node_modules/ms": { 582 | "version": "2.0.0", 583 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 584 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 585 | }, 586 | "node_modules/negotiator": { 587 | "version": "0.6.3", 588 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 589 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 590 | "engines": { 591 | "node": ">= 0.6" 592 | } 593 | }, 594 | "node_modules/node-domexception": { 595 | "version": "1.0.0", 596 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 597 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 598 | "funding": [ 599 | { 600 | "type": "github", 601 | "url": "https://github.com/sponsors/jimmywarting" 602 | }, 603 | { 604 | "type": "github", 605 | "url": "https://paypal.me/jimmywarting" 606 | } 607 | ], 608 | "engines": { 609 | "node": ">=10.5.0" 610 | } 611 | }, 612 | "node_modules/node-fetch": { 613 | "version": "3.3.2", 614 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", 615 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", 616 | "dependencies": { 617 | "data-uri-to-buffer": "^4.0.0", 618 | "fetch-blob": "^3.1.4", 619 | "formdata-polyfill": "^4.0.10" 620 | }, 621 | "engines": { 622 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 623 | }, 624 | "funding": { 625 | "type": "opencollective", 626 | "url": "https://opencollective.com/node-fetch" 627 | } 628 | }, 629 | "node_modules/node-gyp-build": { 630 | "version": "4.7.1", 631 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.1.tgz", 632 | "integrity": "sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==", 633 | "optional": true, 634 | "peer": true, 635 | "bin": { 636 | "node-gyp-build": "bin.js", 637 | "node-gyp-build-optional": "optional.js", 638 | "node-gyp-build-test": "build-test.js" 639 | } 640 | }, 641 | "node_modules/object-assign": { 642 | "version": "4.1.1", 643 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 644 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 645 | "engines": { 646 | "node": ">=0.10.0" 647 | } 648 | }, 649 | "node_modules/object-inspect": { 650 | "version": "1.13.1", 651 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", 652 | "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", 653 | "funding": { 654 | "url": "https://github.com/sponsors/ljharb" 655 | } 656 | }, 657 | "node_modules/on-finished": { 658 | "version": "2.4.1", 659 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 660 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 661 | "dependencies": { 662 | "ee-first": "1.1.1" 663 | }, 664 | "engines": { 665 | "node": ">= 0.8" 666 | } 667 | }, 668 | "node_modules/parseurl": { 669 | "version": "1.3.3", 670 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 671 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 672 | "engines": { 673 | "node": ">= 0.8" 674 | } 675 | }, 676 | "node_modules/path-to-regexp": { 677 | "version": "0.1.7", 678 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 679 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 680 | }, 681 | "node_modules/proxy-addr": { 682 | "version": "2.0.7", 683 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 684 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 685 | "dependencies": { 686 | "forwarded": "0.2.0", 687 | "ipaddr.js": "1.9.1" 688 | }, 689 | "engines": { 690 | "node": ">= 0.10" 691 | } 692 | }, 693 | "node_modules/qs": { 694 | "version": "6.11.0", 695 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 696 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 697 | "dependencies": { 698 | "side-channel": "^1.0.4" 699 | }, 700 | "engines": { 701 | "node": ">=0.6" 702 | }, 703 | "funding": { 704 | "url": "https://github.com/sponsors/ljharb" 705 | } 706 | }, 707 | "node_modules/range-parser": { 708 | "version": "1.2.1", 709 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 710 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 711 | "engines": { 712 | "node": ">= 0.6" 713 | } 714 | }, 715 | "node_modules/raw-body": { 716 | "version": "2.5.1", 717 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 718 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 719 | "dependencies": { 720 | "bytes": "3.1.2", 721 | "http-errors": "2.0.0", 722 | "iconv-lite": "0.4.24", 723 | "unpipe": "1.0.0" 724 | }, 725 | "engines": { 726 | "node": ">= 0.8" 727 | } 728 | }, 729 | "node_modules/safe-buffer": { 730 | "version": "5.2.1", 731 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 732 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 733 | "funding": [ 734 | { 735 | "type": "github", 736 | "url": "https://github.com/sponsors/feross" 737 | }, 738 | { 739 | "type": "patreon", 740 | "url": "https://www.patreon.com/feross" 741 | }, 742 | { 743 | "type": "consulting", 744 | "url": "https://feross.org/support" 745 | } 746 | ] 747 | }, 748 | "node_modules/safer-buffer": { 749 | "version": "2.1.2", 750 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 751 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 752 | }, 753 | "node_modules/send": { 754 | "version": "0.18.0", 755 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 756 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 757 | "dependencies": { 758 | "debug": "2.6.9", 759 | "depd": "2.0.0", 760 | "destroy": "1.2.0", 761 | "encodeurl": "~1.0.2", 762 | "escape-html": "~1.0.3", 763 | "etag": "~1.8.1", 764 | "fresh": "0.5.2", 765 | "http-errors": "2.0.0", 766 | "mime": "1.6.0", 767 | "ms": "2.1.3", 768 | "on-finished": "2.4.1", 769 | "range-parser": "~1.2.1", 770 | "statuses": "2.0.1" 771 | }, 772 | "engines": { 773 | "node": ">= 0.8.0" 774 | } 775 | }, 776 | "node_modules/send/node_modules/ms": { 777 | "version": "2.1.3", 778 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 779 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 780 | }, 781 | "node_modules/serve-static": { 782 | "version": "1.15.0", 783 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 784 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 785 | "dependencies": { 786 | "encodeurl": "~1.0.2", 787 | "escape-html": "~1.0.3", 788 | "parseurl": "~1.3.3", 789 | "send": "0.18.0" 790 | }, 791 | "engines": { 792 | "node": ">= 0.8.0" 793 | } 794 | }, 795 | "node_modules/set-function-length": { 796 | "version": "1.2.0", 797 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", 798 | "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", 799 | "dependencies": { 800 | "define-data-property": "^1.1.1", 801 | "function-bind": "^1.1.2", 802 | "get-intrinsic": "^1.2.2", 803 | "gopd": "^1.0.1", 804 | "has-property-descriptors": "^1.0.1" 805 | }, 806 | "engines": { 807 | "node": ">= 0.4" 808 | } 809 | }, 810 | "node_modules/setprototypeof": { 811 | "version": "1.2.0", 812 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 813 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 814 | }, 815 | "node_modules/side-channel": { 816 | "version": "1.0.4", 817 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 818 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 819 | "dependencies": { 820 | "call-bind": "^1.0.0", 821 | "get-intrinsic": "^1.0.2", 822 | "object-inspect": "^1.9.0" 823 | }, 824 | "funding": { 825 | "url": "https://github.com/sponsors/ljharb" 826 | } 827 | }, 828 | "node_modules/statuses": { 829 | "version": "2.0.1", 830 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 831 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 832 | "engines": { 833 | "node": ">= 0.8" 834 | } 835 | }, 836 | "node_modules/toidentifier": { 837 | "version": "1.0.1", 838 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 839 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 840 | "engines": { 841 | "node": ">=0.6" 842 | } 843 | }, 844 | "node_modules/type-is": { 845 | "version": "1.6.18", 846 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 847 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 848 | "dependencies": { 849 | "media-typer": "0.3.0", 850 | "mime-types": "~2.1.24" 851 | }, 852 | "engines": { 853 | "node": ">= 0.6" 854 | } 855 | }, 856 | "node_modules/unpipe": { 857 | "version": "1.0.0", 858 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 859 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 860 | "engines": { 861 | "node": ">= 0.8" 862 | } 863 | }, 864 | "node_modules/utf-8-validate": { 865 | "version": "5.0.10", 866 | "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", 867 | "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", 868 | "hasInstallScript": true, 869 | "optional": true, 870 | "peer": true, 871 | "dependencies": { 872 | "node-gyp-build": "^4.3.0" 873 | }, 874 | "engines": { 875 | "node": ">=6.14.2" 876 | } 877 | }, 878 | "node_modules/utils-merge": { 879 | "version": "1.0.1", 880 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 881 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 882 | "engines": { 883 | "node": ">= 0.4.0" 884 | } 885 | }, 886 | "node_modules/vary": { 887 | "version": "1.1.2", 888 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 889 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 890 | "engines": { 891 | "node": ">= 0.8" 892 | } 893 | }, 894 | "node_modules/web-streams-polyfill": { 895 | "version": "3.2.1", 896 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 897 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", 898 | "engines": { 899 | "node": ">= 8" 900 | } 901 | } 902 | } 903 | } 904 | --------------------------------------------------------------------------------