Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bada8b8792 | ||
|
|
e93b19c566 | ||
|
|
862f715d05 | ||
|
|
3ed6c38587 | ||
|
|
7e183f3d2c | ||
|
|
901d0954c0 | ||
|
|
caebc1a4ab | ||
|
|
9b419f0c78 | ||
|
|
c67b888eb6 | ||
|
|
376cd11808 | ||
|
|
58132a9478 | ||
|
|
fadcf19206 | ||
|
|
3be17268ab | ||
|
|
82cdc60af6 | ||
|
|
6c9ede6931 |
11
.github/workflows/release.yml
vendored
@@ -17,6 +17,16 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install soldeer
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: soldeer
|
||||
- name: Store soldeer login credential
|
||||
env:
|
||||
SOLDEER_TOKEN: ${{ secrets.SOLDEER_TOKEN }}
|
||||
run: |
|
||||
echo "$SOLDEER_TOKEN" > "$GITHUB_WORKSPACE"/soldeer_login
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -37,6 +47,7 @@ jobs:
|
||||
run: yarn version:publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
SOLDEER_LOGIN_FILE: ${{ github.workspace }}/soldeer_login
|
||||
|
||||
- run: yarn version:release
|
||||
env:
|
||||
|
||||
@@ -264,7 +264,7 @@ The core of the Semaphore protocol is in the [circuit logic](/packages/circuits/
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 🛠 Install
|
||||
|
||||
BIN
apps/docs/assets/img-benchmarks/browser/browser-benchmarks.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 201 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 125 KiB |
@@ -16,10 +16,10 @@
|
||||
"format:write": "remark ./**/*.mdx --output"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.1.1",
|
||||
"@docusaurus/preset-classic": "3.1.1",
|
||||
"@docusaurus/core": "3.5.2",
|
||||
"@docusaurus/preset-classic": "3.5.2",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"clsx": "^1.2.1",
|
||||
"docusaurus-plugin-sass": "^0.2.5",
|
||||
@@ -31,8 +31,8 @@
|
||||
"url-loader": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.1.1",
|
||||
"@docusaurus/tsconfig": "3.1.1",
|
||||
"@docusaurus/module-type-aliases": "3.5.2",
|
||||
"@docusaurus/tsconfig": "3.5.2",
|
||||
"@types/react": "^18.2.29",
|
||||
"remark-cli": "^12.0.0",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
|
||||
@@ -26,7 +26,7 @@ With the Client contract as the owner of the Semaphore contract, the Client
|
||||
contract may call owner-only Semaphore functions such as
|
||||
`addExternalNullifier()`.
|
||||
|
||||
## Add, deactivate, or reactivate external nullifiiers
|
||||
## Add, deactivate, or reactivate external nullifiers
|
||||
|
||||
These functions add, deactivate, and reactivate an external nullifier respectively.
|
||||
As each identity can only signal once to an external nullifier, and as a signal
|
||||
|
||||
@@ -37,7 +37,7 @@ For more information, see [Merkle tree in Wikipedia](https://en.wikipedia.org/wi
|
||||
|
||||
## Nullifier
|
||||
|
||||
A value used to prevent double entry or double signalling.
|
||||
A value used to prevent double entry or double signaling.
|
||||
|
||||
See [Circuit nullifier hash](/V3/technical-reference/circuits/#nullifier-hash).
|
||||
|
||||
|
||||
131
apps/docs/versioned_docs/version-V4/benchmarks.md
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Benchmarks
|
||||
|
||||
Semaphore v4 introduces new features and performance improvements. Detailed changes are available in the [release changelog](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0).
|
||||
|
||||
The primary changes in benchmark values are driven by the two major protocol updates:
|
||||
|
||||
- New [Identity schema](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity).
|
||||
|
||||
- [LeanIMT](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/lean-imt): New optimized IMT.
|
||||
|
||||
## New Identity schema
|
||||
|
||||
Semaphore v4 includes a new schema for the identities allowing the creation and verification of signatures.
|
||||
|
||||
Although the new Identity package is slightly slower than the one in Semaphore v3 (by just a few milliseconds), the trade-off is minimal considering the included functionality.
|
||||
|
||||
The new identity schema adds additional constraints to the Semaphore v4 circuit; however, this does not negatively impact overall performance of the protocol.
|
||||
|
||||
## LeanIMT
|
||||
|
||||
Semaphore v4 uses the LeanIMT data structure for group operations, an improvement over the IMT used in v3.
|
||||
|
||||
For further details, see the [LeanIMT paper](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/papers/leanimt).
|
||||
|
||||
The LeanIMT offers dynamic depth, resulting in faster and more cost-effective group operations, across Node.js, browser and smart contracts.
|
||||
|
||||
Semaphore v4 support tree depths from 1 to 32, while v3 supports depths from 16 to 32, both for proof generation and verification.
|
||||
|
||||
## System Specifications and Software environment
|
||||
|
||||
All the benchmarks were run in an environment with these properties:
|
||||
|
||||
**System Specifications**
|
||||
|
||||
Computer: MacBook Pro
|
||||
|
||||
Chip: Apple M2 Pro
|
||||
|
||||
Memory (RAM): 16 GB
|
||||
|
||||
Operating System: macOS Sequoia version 15.0.1
|
||||
|
||||
**Software environment**
|
||||
|
||||
Node.js version: 20.18.0
|
||||
|
||||
Browser: Google Chrome Version 130.0.6723.92 (Official Build) (arm64)
|
||||
|
||||
## Running the benchmarks
|
||||
|
||||
### Javascript and Circom
|
||||
|
||||
GitHub repository to the run Node.js, browser and Circom benchmarks: https://github.com/vplasencia/semaphore-benchmarks
|
||||
|
||||
### Solidity
|
||||
|
||||
GitHub repository to run the Solidity benchmarks: https://github.com/semaphore-protocol/semaphore
|
||||
|
||||
## Node.js benchmarks
|
||||
|
||||
### Identities
|
||||
|
||||

|
||||
|
||||
### Create Group
|
||||
|
||||
Create group, either empty or with initial members.
|
||||
|
||||

|
||||
|
||||
### Add Member
|
||||
|
||||
Add a member to groups with different sizes.
|
||||
|
||||

|
||||
|
||||
### Generate Proof
|
||||
|
||||
Generate a proof using groups with different numbers of members.
|
||||
|
||||

|
||||
|
||||
### Verify Proof
|
||||
|
||||
Verify a proof using groups with different numbers of members.
|
||||
|
||||

|
||||
|
||||
## Browser benchmarks
|
||||
|
||||
Main functions used in the browser.
|
||||
|
||||

|
||||
|
||||
## Circuit benchmarks
|
||||
|
||||
### Semaphore V3
|
||||
|
||||
<img
|
||||
src={require('../../assets/img-benchmarks/circuits/semaphore-v3-circuits-benchmarks.png').default}
|
||||
alt="Circuit benchmarks Semaphore v3"
|
||||
style={{ width: '300px', height: 'auto' }}
|
||||
/>
|
||||
|
||||
### Semaphore V4
|
||||
|
||||
<img
|
||||
src={require('../../assets/img-benchmarks/circuits/semaphore-v4-circuits-benchmarks.png').default}
|
||||
alt="Circuit benchmarks Semaphore v4"
|
||||
style={{ width: '300px', height: 'auto' }}
|
||||
/>
|
||||
|
||||
## Contracts
|
||||
|
||||
<img
|
||||
src={require('../../assets/img-benchmarks/contracts/contract-benchmarks.png').default}
|
||||
alt="Contract Benchmarks"
|
||||
style={{ width: '590px', height: 'auto' }}
|
||||
/>
|
||||
|
||||
### Semaphore V3 gas report
|
||||
|
||||

|
||||
|
||||
### Semaphore V4 gas report
|
||||
|
||||

|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 12
|
||||
sidebar_position: 13
|
||||
---
|
||||
|
||||
# Credits
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 11
|
||||
sidebar_position: 12
|
||||
---
|
||||
|
||||
# FAQ
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
# Glossary
|
||||
|
||||
@@ -109,3 +109,33 @@ After a message is signed, anyone can verify the signature using the message its
|
||||
// Static method.
|
||||
Identity.verifySignature(message, signature, identity1.publicKey)
|
||||
```
|
||||
|
||||
## Export and import an identity
|
||||
|
||||
A Semaphore Identity can be exported and then imported later for reuse.
|
||||
|
||||
### Export an identity
|
||||
|
||||
Returns the private key encoded as a base64 string.
|
||||
|
||||
```ts
|
||||
import { Identity } from "@semaphore-protocol/identity"
|
||||
|
||||
const identity = new Identity()
|
||||
|
||||
const privateKey = identity.export()
|
||||
```
|
||||
|
||||
### Import an identity
|
||||
|
||||
Returns a Semaphore identity based on a private key encoded as a base64 string.
|
||||
|
||||
```ts
|
||||
import { Identity } from "@semaphore-protocol/identity"
|
||||
|
||||
const identity = new Identity()
|
||||
|
||||
const privateKey = identity.export()
|
||||
|
||||
const identity2 = Identity.import(privateKey)
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 9
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
import Articles from '@site/src/components/Articles';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
sidebar_position: 11
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs"
|
||||
|
||||
@@ -42,17 +42,17 @@
|
||||
|
||||
## Networks
|
||||
|
||||
You can access any subgraph supported by Semaphore with the following URL: https://api.studio.thegraph.com/query/14377/semaphore-<network-name>/v4.0.0-beta.17.
|
||||
You can access any subgraph supported by Semaphore with the following URL: https://api.studio.thegraph.com/query/14377/semaphore-<network-name>/v4.1.0.
|
||||
|
||||
Supported networks:
|
||||
|
||||
- `sepolia`
|
||||
- `optimism`
|
||||
- `optimism-sepolia`
|
||||
- `arbitrum-one`
|
||||
- `arbitrum`
|
||||
- `arbitrum-sepolia`
|
||||
- `matic`
|
||||
- `polygon-amoy`
|
||||
- `matic-amoy`
|
||||
- `base-sepolia`
|
||||
- `base`
|
||||
- `linea-sepolia`
|
||||
|
||||
@@ -555,5 +555,15 @@
|
||||
"github": "https://github.com/GeneralMagicio/pairwise-RPGF4",
|
||||
"website": "https://pairwise.vote"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "VeilEscrow",
|
||||
"categories": ["Privacy", "Coordination"],
|
||||
"tagline": "Secure, private, and decentralized escrows for anonymous transactions",
|
||||
"pse": false,
|
||||
"icon": "",
|
||||
"links": {
|
||||
"github": "https://github.com/evgongora/VeilEscrow"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/circuits",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "Semaphore Circom circuits to generate zero-knowledge proofs.",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-contracts-hardhat",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "Semaphore Hardhat template.",
|
||||
"license": "Unlicense",
|
||||
"files": [
|
||||
@@ -41,9 +41,9 @@
|
||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.0",
|
||||
"@semaphore-protocol/core": "4.4.1",
|
||||
"@semaphore-protocol/hardhat": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/core": "4.6.0",
|
||||
"@semaphore-protocol/hardhat": "4.6.0",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"@typechain/ethers-v6": "^0.5.0",
|
||||
"@typechain/hardhat": "^9.0.0",
|
||||
"@types/chai": "^4.2.0",
|
||||
@@ -71,7 +71,7 @@
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/contracts": "4.4.1"
|
||||
"@semaphore-protocol/contracts": "4.6.0"
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.0",
|
||||
"@semaphore-protocol/core": "4.4.1",
|
||||
"@semaphore-protocol/hardhat": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/core": "4.6.0",
|
||||
"@semaphore-protocol/hardhat": "4.6.0",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"@typechain/ethers-v6": "^0.5.0",
|
||||
"@typechain/hardhat": "^9.0.0",
|
||||
"@types/chai": "^4.2.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/contracts": "4.4.1"
|
||||
"@semaphore-protocol/contracts": "4.6.0"
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/core": "4.4.1",
|
||||
"@semaphore-protocol/data": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/core": "4.6.0",
|
||||
"@semaphore-protocol/data": "4.6.0",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"ethers": "^6.11.1",
|
||||
"next": "14.1.0",
|
||||
"next-pwa": "^5.6.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-monorepo-ethers",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "Semaphore Hardhat + Next.js + SemaphoreEthers template.",
|
||||
"license": "Unlicense",
|
||||
"files": [
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.0",
|
||||
"@semaphore-protocol/core": "4.4.1",
|
||||
"@semaphore-protocol/hardhat": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/core": "4.6.0",
|
||||
"@semaphore-protocol/hardhat": "4.6.0",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"@typechain/ethers-v6": "^0.5.0",
|
||||
"@typechain/hardhat": "^9.0.0",
|
||||
"@types/chai": "^4.2.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/contracts": "4.4.1"
|
||||
"@semaphore-protocol/contracts": "4.6.0"
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/core": "4.4.1",
|
||||
"@semaphore-protocol/data": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/core": "4.6.0",
|
||||
"@semaphore-protocol/data": "4.6.0",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"ethers": "^6.11.1",
|
||||
"next": "14.1.0",
|
||||
"next-pwa": "^5.6.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli-template-monorepo-subgraph",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "Semaphore Hardhat + Next.js + SemaphoreSubgraph template.",
|
||||
"license": "Unlicense",
|
||||
"files": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/cli",
|
||||
"type": "module",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A command line tool to set up your Semaphore project and get group data.",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -41,8 +41,8 @@
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/data": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/data": "4.6.0",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"axios": "^1.6.7",
|
||||
"boxen": "^7.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
|
||||
@@ -13,6 +13,7 @@ import checkLatestVersion from "./checkLatestVersion.js"
|
||||
import getGroupIds from "./getGroupIds.js"
|
||||
import { getGroupId, getProjectName, getSupportedNetwork, getSupportedTemplate } from "./inquirerPrompts.js"
|
||||
import Spinner from "./spinner.js"
|
||||
import removePrePublishScript from "./removePrePublishScript.js"
|
||||
|
||||
// Define the path to the package.json file to extract metadata for the CLI.
|
||||
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
|
||||
@@ -103,6 +104,12 @@ program
|
||||
// Create an empty yarn.lock file to install dependencies successfully
|
||||
writeFileSync(`${currentDirectory}/${projectDirectory}/yarn.lock`, "")
|
||||
|
||||
// Read and modify package.json to remove prepublish script
|
||||
const packageJsonPath = `${currentDirectory}/${projectDirectory}/package.json`
|
||||
const packageJsonContent = readFileSync(packageJsonPath, "utf8")
|
||||
const updatedPackageJsonContent = removePrePublishScript(packageJsonContent)
|
||||
writeFileSync(packageJsonPath, updatedPackageJsonContent)
|
||||
|
||||
spinner.stop()
|
||||
|
||||
console.info(`\n ${logSymbols.success}`, `Your project is ready!\n`)
|
||||
@@ -111,7 +118,7 @@ program
|
||||
console.info(` ${chalk.cyan("yarn install")}\n`)
|
||||
|
||||
// Read the package.json to list available npm scripts.
|
||||
const { scripts } = JSON.parse(readFileSync(`${currentDirectory}/${projectDirectory}/package.json`, "utf8"))
|
||||
const { scripts } = JSON.parse(updatedPackageJsonContent)
|
||||
|
||||
if (scripts) {
|
||||
console.info(` Available scripts:\n`)
|
||||
|
||||
16
packages/cli/src/removePrePublishScript.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// Remove the prepublish script from the package.json file when creating a new project using the Semaphore CLI.
|
||||
export default function removePrePublishScript(packageJsonContent: string): string {
|
||||
try {
|
||||
const packageJson = JSON.parse(packageJsonContent)
|
||||
if (packageJson.scripts && "prepublish" in packageJson.scripts) {
|
||||
delete packageJson.scripts.prepublish
|
||||
if (Object.keys(packageJson.scripts).length === 0) {
|
||||
delete packageJson.scripts
|
||||
}
|
||||
}
|
||||
return JSON.stringify(packageJson, null, 2)
|
||||
} catch (error) {
|
||||
console.error("Error processing package.json:", error)
|
||||
return packageJsonContent
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
import {ISemaphore} from "./interfaces/ISemaphore.sol";
|
||||
import {ISemaphoreVerifier} from "./interfaces/ISemaphoreVerifier.sol";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
/// @dev Minimum supported tree depth.
|
||||
uint8 constant MIN_DEPTH = 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
import {ISemaphoreGroups} from "../interfaces/ISemaphoreGroups.sol";
|
||||
import {InternalLeanIMT, LeanIMTData} from "@zk-kit/lean-imt.sol/InternalLeanIMT.sol";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Part of this file was generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
import {MAX_DEPTH} from "./Constants.sol";
|
||||
import {SemaphoreVerifierKeyPts} from "./SemaphoreVerifierKeyPts.sol";
|
||||
@@ -59,7 +59,10 @@ contract SemaphoreVerifier {
|
||||
mstore(add(mIn, 32), y)
|
||||
mstore(add(mIn, 64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
// ecMul gas cost is fixed at 6000. Add 33.3% gas for safety buffer.
|
||||
// Last checked in 2024 Oct, evm codename Cancun
|
||||
// ref: https://www.evm.codes/precompiled?fork=cancun#0x07
|
||||
success := staticcall(8000, 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
@@ -69,7 +72,10 @@ contract SemaphoreVerifier {
|
||||
mstore(add(mIn, 64), mload(pR))
|
||||
mstore(add(mIn, 96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
// ecAdd gas cost is fixed at 150. Add 33.3% gas for safety buffer.
|
||||
// Last checked in 2024 Oct, evm codename Cancun
|
||||
// ref: https://www.evm.codes/precompiled?fork=cancun#0x06
|
||||
success := staticcall(200, 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
@@ -149,7 +155,10 @@ contract SemaphoreVerifier {
|
||||
mstore(add(_pPairing, 704), mload(add(vkPoints, 64)))
|
||||
mstore(add(_pPairing, 736), mload(add(vkPoints, 96)))
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
|
||||
// ecPairing gas cost at 181000 given 768 bytes input. Add 33.3% gas for safety buffer.
|
||||
// Last checked in 2024 Oct, evm codename Cancun
|
||||
// ref: https://www.evm.codes/precompiled?fork=cancun#0x08
|
||||
let success := staticcall(241333, 8, _pPairing, 768, _pPairing, 0x20)
|
||||
|
||||
isOk := and(success, mload(_pPairing))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Part of this file was generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
library SemaphoreVerifierKeyPts {
|
||||
error Semaphore__VKPtBytesMaxDepthInvariantViolated(uint256 actual, uint256 expected);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
/// @title Semaphore contract interface.
|
||||
interface ISemaphore {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
/// @title SemaphoreGroups contract interface.
|
||||
interface ISemaphoreGroups {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.23;
|
||||
pragma solidity >=0.8.23 <=0.8.28;
|
||||
|
||||
/// @title SemaphoreVerifier contract interface.
|
||||
interface ISemaphoreVerifier {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/contracts",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "Semaphore contracts to manage groups and broadcast anonymous signals.",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/core",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "Core library for the essential Semaphore features.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -42,8 +42,8 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/group": "4.4.1",
|
||||
"@semaphore-protocol/identity": "4.4.1",
|
||||
"@semaphore-protocol/proof": "4.4.1"
|
||||
"@semaphore-protocol/group": "4.6.0",
|
||||
"@semaphore-protocol/identity": "4.6.0",
|
||||
"@semaphore-protocol/proof": "4.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/data",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A library for querying Semaphore smart contract.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -37,7 +37,7 @@
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"axios": "1.6.6",
|
||||
"ethers": "6.11.0"
|
||||
}
|
||||
|
||||
@@ -12,5 +12,5 @@ export default function getURL(supportedNetwork: SupportedNetwork): string {
|
||||
throw new TypeError(`Network '${supportedNetwork}' is not supported`)
|
||||
}
|
||||
|
||||
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.0.0`
|
||||
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.1.0`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/group",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A library to create and manage Semaphore groups.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/hardhat",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A Hardhat plugin to deploy Semaphore contracts.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -41,7 +41,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nomicfoundation/hardhat-ethers": "^3.0.0",
|
||||
"@semaphore-protocol/contracts": "4.4.1",
|
||||
"@semaphore-protocol/contracts": "4.6.0",
|
||||
"ethers": "^6.4.0",
|
||||
"hardhat-dependency-compiler": "^1.1.3"
|
||||
}
|
||||
|
||||
@@ -129,3 +129,11 @@ const signature = identity.signMessage(message)
|
||||
|
||||
Identity.verifySignature(message, signature, identity.publicKey)
|
||||
```
|
||||
|
||||
\# **Identity.generateCommitment**(publicKey: _Point_): _bigint_
|
||||
|
||||
```typescript
|
||||
import { Identity } from "@semaphore-protocol/identity"
|
||||
|
||||
Identity.generateCommitment(identity.publicKey)
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/identity",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A library to create Semaphore identities.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import type { Point } from "@zk-kit/baby-jubjub"
|
||||
import { EdDSAPoseidon, Signature, signMessage, verifySignature } from "@zk-kit/eddsa-poseidon"
|
||||
import { EdDSAPoseidon, type Signature, signMessage, verifySignature } from "@zk-kit/eddsa-poseidon"
|
||||
import type { BigNumberish } from "@zk-kit/utils"
|
||||
import { base64ToBuffer, bufferToBase64, textToBase64 } from "@zk-kit/utils/conversions"
|
||||
import { isString } from "@zk-kit/utils/type-checks"
|
||||
import { poseidon2 } from "poseidon-lite/poseidon2"
|
||||
|
||||
export type { Point }
|
||||
export type { Signature }
|
||||
|
||||
/**
|
||||
* The Semaphore identity is essentially an {@link https://www.rfc-editor.org/rfc/rfc8032 | EdDSA}
|
||||
* public/private key pair. The {@link https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/eddsa-poseidon | EdDSA implementation}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/proof",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A library to generate and verify Semaphore proofs.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -47,11 +47,11 @@
|
||||
"rollup-plugin-cleanup": "^3.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@semaphore-protocol/group": "4.4.1",
|
||||
"@semaphore-protocol/identity": "4.4.1"
|
||||
"@semaphore-protocol/group": "4.6.0",
|
||||
"@semaphore-protocol/identity": "4.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semaphore-protocol/utils": "4.4.1",
|
||||
"@semaphore-protocol/utils": "4.6.0",
|
||||
"@zk-kit/artifacts": "1.8.0",
|
||||
"@zk-kit/utils": "1.2.1",
|
||||
"ethers": "6.10.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@semaphore-protocol/utils",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.0",
|
||||
"description": "A library to provide utility functions to the other Semaphore packages.",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 6333999
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 6983614
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 6333999
|
||||
"startBlock": 6983614
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 6333999
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 6983614
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -24,18 +24,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 64798522
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 93258221
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 64798522
|
||||
"startBlock": 93258221
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 64798522
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 93258221
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -44,18 +44,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 14757931
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 19289434
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 14757931
|
||||
"startBlock": 19289434
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 14757931
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 19289434
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -64,18 +64,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 9636193
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 13850778
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 9636193
|
||||
"startBlock": 13850778
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 9636193
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 13850778
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -84,18 +84,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 258951463
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 269586534
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 258951463
|
||||
"startBlock": 269586534
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 258951463
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 269586534
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -104,18 +104,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 62466952
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 63715311
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 62466952
|
||||
"startBlock": 63715311
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 62466952
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 63715311
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -124,18 +124,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 126057798
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 127391657
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 126057798
|
||||
"startBlock": 127391657
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 126057798
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 127391657
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -144,18 +144,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 16008294
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 17307202
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 16008294
|
||||
"startBlock": 17307202
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 16008294
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 17307202
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -164,18 +164,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 3928632
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 5225214
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 3928632
|
||||
"startBlock": 5225214
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 3928632
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 5225214
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -184,18 +184,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 20553357
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 21796660
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 20553357
|
||||
"startBlock": 21796660
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 20553357
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 21796660
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -204,18 +204,18 @@
|
||||
"contracts": [
|
||||
{
|
||||
"name": "SemaphoreVerifier",
|
||||
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043",
|
||||
"startBlock": 10235849
|
||||
"address": "0x6C42599435B82121794D835263C846384869502d",
|
||||
"startBlock": 11459722
|
||||
},
|
||||
{
|
||||
"name": "PoseidonT3",
|
||||
"address": "0xB43122Ecb241DD50062641f089876679fd06599a",
|
||||
"startBlock": 10235849
|
||||
"startBlock": 11459722
|
||||
},
|
||||
{
|
||||
"name": "Semaphore",
|
||||
"address": "0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f",
|
||||
"startBlock": 10235849
|
||||
"address": "0x06d1530c829366A7fff0069e77c5af6A6FA7db2E",
|
||||
"startBlock": 11459722
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!node_modules/.bin/ts-node
|
||||
#!/usr/bin/env ts-node
|
||||
import { readdirSync, rmSync } from "fs"
|
||||
|
||||
const folderName = "apps"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!node_modules/.bin/ts-node
|
||||
#!/usr/bin/env ts-node
|
||||
import { rmSync } from "fs"
|
||||
|
||||
const folderName = "packages"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!node_modules/.bin/ts-node
|
||||
#!/usr/bin/env ts-node
|
||||
import { readdirSync, rmSync } from "fs"
|
||||
|
||||
const folderName = "packages"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!node_modules/.bin/ts-node
|
||||
#!/usr/bin/env ts-node
|
||||
import compare from "semver/functions/compare"
|
||||
import { execSync } from "child_process"
|
||||
import contractsPkgJson from "@semaphore-protocol/contracts/package.json"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!node_modules/.bin/ts-node
|
||||
#!/usr/bin/env ts-node
|
||||
import { readFileSync, readdirSync, writeFileSync } from "node:fs"
|
||||
|
||||
const folderName = "packages"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!node_modules/.bin/ts-node
|
||||
#!/usr/bin/env ts-node
|
||||
import { execSync } from "child_process"
|
||||
|
||||
async function main() {
|
||||
|
||||