├── .github
└── workflows
│ ├── build.yml
│ └── main.yml
├── .gitignore
├── .gitmodules
├── .npmignore
├── browser
├── bls.js
├── demo.html
├── demo.js
├── package-lock.json
├── package.json
├── readme.md
└── webpack.config.js
├── package-lock.json
├── package.json
├── readme.md
├── src
├── Makefile
├── bls.js
├── bls_c.js
├── index.d.ts
└── index.js
└── test
├── aggregate.txt
├── aggregate_verify.txt
├── bench.js
├── fast_aggregate_verify.txt
├── mcl-test.js
├── sign.txt
├── test.js
└── verify.txt
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | permissions:
4 | contents: write
5 | repository-projects: write
6 |
7 | on:
8 | workflow_dispatch:
9 | branches: [dev]
10 |
11 | jobs:
12 | build:
13 | name: bls-eth-wasm
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | - name: node
18 | uses: actions/setup-node@v4
19 | with:
20 | node-version: "20"
21 | env:
22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 | - run: |
24 | git pull
25 | cur=$(git rev-parse --abbrev-ref HEAD)
26 | echo "current branch is $cur."
27 | if [ "$cur" != "dev" ]; then
28 | echo "err : not dev branch"
29 | exit 1
30 | fi
31 | git config user.name github-actions
32 | git config user.email github-actions@github.com
33 | git clone https://github.com/emscripten-core/emsdk.git
34 | cd emsdk/
35 | ./emsdk install latest
36 | ./emsdk activate latest
37 | source ./emsdk_env.sh
38 | emcc -v
39 | cd ..
40 | git submodule update --init --recursive
41 | make -C src
42 | cd browser
43 | npm install -D webpack webpack-cli
44 | npx webpack
45 | cd ..
46 | npm test
47 | sha256sum src/bls_c.js browser/bls.js
48 | git add -f src/bls_c.js browser/bls.js
49 | changes=$(git diff --staged --numstat | wc -l)
50 | if [[ $changes -gt 0 ]]
51 | then
52 | git commit -m "build: bls_c.js is generated by GitHub Action"
53 | git push origin dev
54 | fi
55 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: test
2 | on: [push]
3 |
4 | jobs:
5 | build:
6 | name: test
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v4
10 | - name: node
11 | uses: actions/setup-node@v4
12 | with:
13 | node-version: '20'
14 | - run: node test/test.js
15 | - run: node test/mcl-test.js
16 |
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | browser-demo/dist/
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/bls"]
2 | path = src/bls
3 | url = https://github.com/herumi/bls
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bls-demo.html
2 | bls-demo.js
3 | index-browser.js
4 | .nyc_output/
5 | coverage/
6 | test/
7 | t.js
8 | bls2.js
9 | test2.js
10 | bls.wasm
11 | .travis.yml
12 |
--------------------------------------------------------------------------------
/browser/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BLS signature sample
6 |
7 |
8 |
9 |
10 |
11 | pairing parameter : BLS12_381
12 | library status initializing...
13 |
group order : 0
14 |
15 |
16 | sign : 0msec
17 | verify : 0msec
18 |
19 |
20 |
21 | secretKey :
22 | publicKey :
23 | msg :
24 | signature :
25 | verify :
26 |
27 |
28 |
29 | threshold(k) :
30 | number of players(n) :
31 | master secret key :
32 | master public key :
33 | msg :
34 | signature :
35 |
36 | key sharing
37 |
38 | key recover
39 |
40 | selected index of id :
41 | recover secret key :
42 | recover public key :
43 | recover signature :
44 |
45 |
46 |
47 |
48 | id(dec) =
49 | sec =
50 |
51 | id(dec) again =
52 | id(hex) =
53 | sec.serialize =
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/browser/demo.js:
--------------------------------------------------------------------------------
1 | function getValue (name) { return document.getElementsByName(name)[0].value }
2 | function setValue (name, val) { document.getElementsByName(name)[0].value = val }
3 | function getText (name) { return document.getElementsByName(name)[0].innerText }
4 | function setText (name, val) { document.getElementsByName(name)[0].innerText = val }
5 |
6 | bls.init(bls.BLS12_381)
7 | .then(() => {
8 | setText('status', 'ok')
9 | setText('curveOrder', bls.getCurveOrder())
10 | })
11 |
12 | function rand (val) {
13 | const x = new bls.Id()
14 | x.setByCSPRNG()
15 | setValue(val, x.serializeToHexStr())
16 | }
17 |
18 | function bench (label, count, func) {
19 | const start = Date.now()
20 | for (let i = 0; i < count; i++) {
21 | func()
22 | }
23 | const end = Date.now()
24 | const t = (end - start) / count
25 | setText(label, t)
26 | }
27 |
28 | function benchBls () {
29 | const sec = new bls.SecretKey()
30 | sec.setByCSPRNG()
31 | const pub = sec.getPublicKey()
32 | const msg = 'abc'
33 | bench('time_sign_class', 50, () => sec.sign(msg))
34 | const sig = sec.sign(msg)
35 | bench('time_verify_class', 50, () => pub.verify(sig, msg))
36 | }
37 | function onClickBenchmark () {
38 | benchBls()
39 | }
40 |
41 | function onClickTestSignature () {
42 | const sec = new bls.SecretKey()
43 |
44 | sec.setByCSPRNG()
45 | setText('secretKey', sec.serializeToHexStr())
46 |
47 | const pub = sec.getPublicKey()
48 | setText('publicKey', pub.serializeToHexStr())
49 |
50 | const msg = getValue('msg')
51 | console.log('msg=' + msg)
52 | const sig = sec.sign(msg)
53 | setText('signature', sig.serializeToHexStr())
54 |
55 | const r = pub.verify(sig, msg)
56 | setText('verifyResult', r ? 'ok' : 'err')
57 | }
58 |
59 | /*
60 | return [min, max)
61 | assume min < max
62 | */
63 | function randRange (min, max) {
64 | return min + Math.floor(Math.random() * (max - min))
65 | }
66 | /*
67 | select k of [0, n)
68 | @note not uniformal distribution
69 | */
70 | function randSelect (k, n) {
71 | const a = []
72 | let prev = -1
73 | for (let i = 0; i < k; i++) {
74 | let v = randRange(prev + 1, n - (k - i) + 1)
75 | a.push(v)
76 | prev = v
77 | }
78 | return a
79 | }
80 |
81 | function onClickTestMisc () {
82 | const idDec = getValue('idDec')
83 | console.log('idDec=' + idDec)
84 | const id = new bls.Id()
85 | id.setStr(idDec)
86 | setText('idDec2', id.getStr())
87 | setText('idHex', id.getStr(16))
88 | const sec = new bls.SecretKey()
89 | sec.setLittleEndian(bls.fromHexStr(getValue('sec1')))
90 | setText('secSerialize', sec.serializeToHexStr())
91 | }
92 |
93 | function onClickTestShare () {
94 | let k = parseInt(getValue('ss_k'))
95 | let n = parseInt(getValue('ss_n'))
96 | let msg = getValue('msg2')
97 | console.log('k = ' + k)
98 | console.log('n = ' + n)
99 | console.log('msg = ' + msg)
100 | if (n < k) {
101 | alert('err : n is smaller than k')
102 | return
103 | }
104 | let msk = []
105 | let mpk = []
106 | let idVec = []
107 | let secVec = []
108 | let pubVec = []
109 | let sigVec = []
110 |
111 | /*
112 | setup master secret key
113 | */
114 | for (let i = 0; i < k; i++) {
115 | let sk = new bls.SecretKey()
116 | sk.setByCSPRNG()
117 | msk.push(sk)
118 |
119 | let pk = sk.getPublicKey()
120 | mpk.push(pk)
121 | }
122 | setText('msk', msk[0].serializeToHexStr())
123 | setText('mpk', mpk[0].serializeToHexStr())
124 | {
125 | let sig = msk[0].sign(msg)
126 | setText('signature2', sig.serializeToHexStr())
127 | console.log('mpk[0] verify ' + mpk[0].verify(sig, msg))
128 | }
129 |
130 | /*
131 | key sharing
132 | */
133 | for (let i = 0; i < n; i++) {
134 | let id = new bls.Id()
135 | // blsIdSetInt(id, i + 1)
136 | id.setByCSPRNG()
137 | idVec.push(id)
138 | let sk = new bls.SecretKey()
139 | sk.share(msk, idVec[i])
140 | secVec.push(sk)
141 |
142 | let pk = new bls.PublicKey()
143 | pk.share(mpk, idVec[i])
144 | pubVec.push(pk)
145 |
146 | let sig = sk.sign(msg)
147 | sigVec.push(sig)
148 | console.log(i + ' : verify msg : ' + pk.verify(sig, msg))
149 | }
150 |
151 | const o = document.getElementById('idlist')
152 | const ol = document.createElement('ol')
153 | let t = ''
154 | for (let i = 0; i < n; i++) {
155 | const id = idVec[i].serializeToHexStr()
156 | const sk = secVec[i].serializeToHexStr()
157 | const pk = pubVec[i].serializeToHexStr()
158 | const sig = sigVec[i].serializeToHexStr()
159 | t += ' '
160 | t += 'id : ' + id + '
'
161 | t += 'pk : ' + pk + '
'
162 | t += 'sk : ' + sk + '
'
163 | t += 'sig: ' + sig + '
'
164 | }
165 | ol.innerHTML = t
166 | o.firstElementChild.innerHTML = ol.innerHTML
167 |
168 | /*
169 | recover
170 | */
171 | const idxVec = randSelect(k, n)
172 | setText('idxVec', idxVec.toString())
173 | const subIdVec = []
174 | const subSecVec = []
175 | const subPubVec = []
176 | const subSigVec = []
177 | for (let i = 0; i < idxVec.length; i++) {
178 | const idx = idxVec[i]
179 | subIdVec.push(idVec[idx])
180 | subSecVec.push(secVec[idx])
181 | subPubVec.push(pubVec[idx])
182 | subSigVec.push(sigVec[idx])
183 | }
184 | {
185 | const sec = new bls.SecretKey()
186 | const pub = new bls.PublicKey()
187 | const sig = new bls.Signature()
188 |
189 | sec.recover(subSecVec, subIdVec)
190 | pub.recover(subPubVec, subIdVec)
191 | sig.recover(subSigVec, subIdVec)
192 | let s = sec.serializeToHexStr()
193 | s += s === getText('msk') ? ' :ok' : ' :ng'
194 | setText('recoverSec', s)
195 | s = pub.serializeToHexStr()
196 | s += s === getText('mpk') ? ' :ok' : ' :ng'
197 | setText('recoverPub', s)
198 | s = sig.serializeToHexStr()
199 | s += s === getText('signature2') ? ' :ok' : ' :ng'
200 | setText('recoverSig', s)
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/browser/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "demo",
9 | "version": "1.0.0",
10 | "license": "BSD-3-Clause",
11 | "devDependencies": {
12 | "webpack": "^5.37.0",
13 | "webpack-cli": "^4.7.0"
14 | }
15 | },
16 | "node_modules/@discoveryjs/json-ext": {
17 | "version": "0.5.7",
18 | "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
19 | "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
20 | "dev": true,
21 | "engines": {
22 | "node": ">=10.0.0"
23 | }
24 | },
25 | "node_modules/@jridgewell/gen-mapping": {
26 | "version": "0.3.5",
27 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
28 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
29 | "dev": true,
30 | "dependencies": {
31 | "@jridgewell/set-array": "^1.2.1",
32 | "@jridgewell/sourcemap-codec": "^1.4.10",
33 | "@jridgewell/trace-mapping": "^0.3.24"
34 | },
35 | "engines": {
36 | "node": ">=6.0.0"
37 | }
38 | },
39 | "node_modules/@jridgewell/resolve-uri": {
40 | "version": "3.1.2",
41 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
42 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
43 | "dev": true,
44 | "engines": {
45 | "node": ">=6.0.0"
46 | }
47 | },
48 | "node_modules/@jridgewell/set-array": {
49 | "version": "1.2.1",
50 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
51 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
52 | "dev": true,
53 | "engines": {
54 | "node": ">=6.0.0"
55 | }
56 | },
57 | "node_modules/@jridgewell/source-map": {
58 | "version": "0.3.6",
59 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
60 | "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
61 | "dev": true,
62 | "dependencies": {
63 | "@jridgewell/gen-mapping": "^0.3.5",
64 | "@jridgewell/trace-mapping": "^0.3.25"
65 | }
66 | },
67 | "node_modules/@jridgewell/sourcemap-codec": {
68 | "version": "1.5.0",
69 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
70 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
71 | "dev": true
72 | },
73 | "node_modules/@jridgewell/trace-mapping": {
74 | "version": "0.3.25",
75 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
76 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
77 | "dev": true,
78 | "dependencies": {
79 | "@jridgewell/resolve-uri": "^3.1.0",
80 | "@jridgewell/sourcemap-codec": "^1.4.14"
81 | }
82 | },
83 | "node_modules/@types/estree": {
84 | "version": "1.0.5",
85 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
86 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
87 | "dev": true
88 | },
89 | "node_modules/@types/json-schema": {
90 | "version": "7.0.15",
91 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
92 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
93 | "dev": true
94 | },
95 | "node_modules/@types/node": {
96 | "version": "22.5.2",
97 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz",
98 | "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==",
99 | "dev": true,
100 | "dependencies": {
101 | "undici-types": "~6.19.2"
102 | }
103 | },
104 | "node_modules/@webassemblyjs/ast": {
105 | "version": "1.12.1",
106 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
107 | "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
108 | "dev": true,
109 | "dependencies": {
110 | "@webassemblyjs/helper-numbers": "1.11.6",
111 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
112 | }
113 | },
114 | "node_modules/@webassemblyjs/floating-point-hex-parser": {
115 | "version": "1.11.6",
116 | "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
117 | "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
118 | "dev": true
119 | },
120 | "node_modules/@webassemblyjs/helper-api-error": {
121 | "version": "1.11.6",
122 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
123 | "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
124 | "dev": true
125 | },
126 | "node_modules/@webassemblyjs/helper-buffer": {
127 | "version": "1.12.1",
128 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
129 | "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
130 | "dev": true
131 | },
132 | "node_modules/@webassemblyjs/helper-numbers": {
133 | "version": "1.11.6",
134 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
135 | "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
136 | "dev": true,
137 | "dependencies": {
138 | "@webassemblyjs/floating-point-hex-parser": "1.11.6",
139 | "@webassemblyjs/helper-api-error": "1.11.6",
140 | "@xtuc/long": "4.2.2"
141 | }
142 | },
143 | "node_modules/@webassemblyjs/helper-wasm-bytecode": {
144 | "version": "1.11.6",
145 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
146 | "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
147 | "dev": true
148 | },
149 | "node_modules/@webassemblyjs/helper-wasm-section": {
150 | "version": "1.12.1",
151 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
152 | "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
153 | "dev": true,
154 | "dependencies": {
155 | "@webassemblyjs/ast": "1.12.1",
156 | "@webassemblyjs/helper-buffer": "1.12.1",
157 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
158 | "@webassemblyjs/wasm-gen": "1.12.1"
159 | }
160 | },
161 | "node_modules/@webassemblyjs/ieee754": {
162 | "version": "1.11.6",
163 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
164 | "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
165 | "dev": true,
166 | "dependencies": {
167 | "@xtuc/ieee754": "^1.2.0"
168 | }
169 | },
170 | "node_modules/@webassemblyjs/leb128": {
171 | "version": "1.11.6",
172 | "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
173 | "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
174 | "dev": true,
175 | "dependencies": {
176 | "@xtuc/long": "4.2.2"
177 | }
178 | },
179 | "node_modules/@webassemblyjs/utf8": {
180 | "version": "1.11.6",
181 | "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
182 | "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
183 | "dev": true
184 | },
185 | "node_modules/@webassemblyjs/wasm-edit": {
186 | "version": "1.12.1",
187 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
188 | "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
189 | "dev": true,
190 | "dependencies": {
191 | "@webassemblyjs/ast": "1.12.1",
192 | "@webassemblyjs/helper-buffer": "1.12.1",
193 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
194 | "@webassemblyjs/helper-wasm-section": "1.12.1",
195 | "@webassemblyjs/wasm-gen": "1.12.1",
196 | "@webassemblyjs/wasm-opt": "1.12.1",
197 | "@webassemblyjs/wasm-parser": "1.12.1",
198 | "@webassemblyjs/wast-printer": "1.12.1"
199 | }
200 | },
201 | "node_modules/@webassemblyjs/wasm-gen": {
202 | "version": "1.12.1",
203 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
204 | "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
205 | "dev": true,
206 | "dependencies": {
207 | "@webassemblyjs/ast": "1.12.1",
208 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
209 | "@webassemblyjs/ieee754": "1.11.6",
210 | "@webassemblyjs/leb128": "1.11.6",
211 | "@webassemblyjs/utf8": "1.11.6"
212 | }
213 | },
214 | "node_modules/@webassemblyjs/wasm-opt": {
215 | "version": "1.12.1",
216 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
217 | "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
218 | "dev": true,
219 | "dependencies": {
220 | "@webassemblyjs/ast": "1.12.1",
221 | "@webassemblyjs/helper-buffer": "1.12.1",
222 | "@webassemblyjs/wasm-gen": "1.12.1",
223 | "@webassemblyjs/wasm-parser": "1.12.1"
224 | }
225 | },
226 | "node_modules/@webassemblyjs/wasm-parser": {
227 | "version": "1.12.1",
228 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
229 | "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
230 | "dev": true,
231 | "dependencies": {
232 | "@webassemblyjs/ast": "1.12.1",
233 | "@webassemblyjs/helper-api-error": "1.11.6",
234 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
235 | "@webassemblyjs/ieee754": "1.11.6",
236 | "@webassemblyjs/leb128": "1.11.6",
237 | "@webassemblyjs/utf8": "1.11.6"
238 | }
239 | },
240 | "node_modules/@webassemblyjs/wast-printer": {
241 | "version": "1.12.1",
242 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
243 | "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
244 | "dev": true,
245 | "dependencies": {
246 | "@webassemblyjs/ast": "1.12.1",
247 | "@xtuc/long": "4.2.2"
248 | }
249 | },
250 | "node_modules/@webpack-cli/configtest": {
251 | "version": "1.2.0",
252 | "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
253 | "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
254 | "dev": true,
255 | "peerDependencies": {
256 | "webpack": "4.x.x || 5.x.x",
257 | "webpack-cli": "4.x.x"
258 | }
259 | },
260 | "node_modules/@webpack-cli/info": {
261 | "version": "1.5.0",
262 | "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
263 | "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
264 | "dev": true,
265 | "dependencies": {
266 | "envinfo": "^7.7.3"
267 | },
268 | "peerDependencies": {
269 | "webpack-cli": "4.x.x"
270 | }
271 | },
272 | "node_modules/@webpack-cli/serve": {
273 | "version": "1.7.0",
274 | "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
275 | "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
276 | "dev": true,
277 | "peerDependencies": {
278 | "webpack-cli": "4.x.x"
279 | },
280 | "peerDependenciesMeta": {
281 | "webpack-dev-server": {
282 | "optional": true
283 | }
284 | }
285 | },
286 | "node_modules/@xtuc/ieee754": {
287 | "version": "1.2.0",
288 | "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
289 | "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
290 | "dev": true
291 | },
292 | "node_modules/@xtuc/long": {
293 | "version": "4.2.2",
294 | "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
295 | "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
296 | "dev": true
297 | },
298 | "node_modules/acorn": {
299 | "version": "8.12.1",
300 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
301 | "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
302 | "dev": true,
303 | "bin": {
304 | "acorn": "bin/acorn"
305 | },
306 | "engines": {
307 | "node": ">=0.4.0"
308 | }
309 | },
310 | "node_modules/acorn-import-attributes": {
311 | "version": "1.9.5",
312 | "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
313 | "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
314 | "dev": true,
315 | "peerDependencies": {
316 | "acorn": "^8"
317 | }
318 | },
319 | "node_modules/ajv": {
320 | "version": "6.12.6",
321 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
322 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
323 | "dev": true,
324 | "dependencies": {
325 | "fast-deep-equal": "^3.1.1",
326 | "fast-json-stable-stringify": "^2.0.0",
327 | "json-schema-traverse": "^0.4.1",
328 | "uri-js": "^4.2.2"
329 | },
330 | "funding": {
331 | "type": "github",
332 | "url": "https://github.com/sponsors/epoberezkin"
333 | }
334 | },
335 | "node_modules/ajv-keywords": {
336 | "version": "3.5.2",
337 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
338 | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
339 | "dev": true,
340 | "peerDependencies": {
341 | "ajv": "^6.9.1"
342 | }
343 | },
344 | "node_modules/browserslist": {
345 | "version": "4.23.3",
346 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
347 | "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
348 | "dev": true,
349 | "funding": [
350 | {
351 | "type": "opencollective",
352 | "url": "https://opencollective.com/browserslist"
353 | },
354 | {
355 | "type": "tidelift",
356 | "url": "https://tidelift.com/funding/github/npm/browserslist"
357 | },
358 | {
359 | "type": "github",
360 | "url": "https://github.com/sponsors/ai"
361 | }
362 | ],
363 | "dependencies": {
364 | "caniuse-lite": "^1.0.30001646",
365 | "electron-to-chromium": "^1.5.4",
366 | "node-releases": "^2.0.18",
367 | "update-browserslist-db": "^1.1.0"
368 | },
369 | "bin": {
370 | "browserslist": "cli.js"
371 | },
372 | "engines": {
373 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
374 | }
375 | },
376 | "node_modules/buffer-from": {
377 | "version": "1.1.2",
378 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
379 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
380 | "dev": true
381 | },
382 | "node_modules/caniuse-lite": {
383 | "version": "1.0.30001655",
384 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz",
385 | "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==",
386 | "dev": true,
387 | "funding": [
388 | {
389 | "type": "opencollective",
390 | "url": "https://opencollective.com/browserslist"
391 | },
392 | {
393 | "type": "tidelift",
394 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
395 | },
396 | {
397 | "type": "github",
398 | "url": "https://github.com/sponsors/ai"
399 | }
400 | ]
401 | },
402 | "node_modules/chrome-trace-event": {
403 | "version": "1.0.4",
404 | "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
405 | "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
406 | "dev": true,
407 | "engines": {
408 | "node": ">=6.0"
409 | }
410 | },
411 | "node_modules/clone-deep": {
412 | "version": "4.0.1",
413 | "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
414 | "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
415 | "dev": true,
416 | "dependencies": {
417 | "is-plain-object": "^2.0.4",
418 | "kind-of": "^6.0.2",
419 | "shallow-clone": "^3.0.0"
420 | },
421 | "engines": {
422 | "node": ">=6"
423 | }
424 | },
425 | "node_modules/colorette": {
426 | "version": "2.0.20",
427 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
428 | "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
429 | "dev": true
430 | },
431 | "node_modules/commander": {
432 | "version": "2.20.3",
433 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
434 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
435 | "dev": true
436 | },
437 | "node_modules/cross-spawn": {
438 | "version": "7.0.3",
439 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
440 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
441 | "dev": true,
442 | "dependencies": {
443 | "path-key": "^3.1.0",
444 | "shebang-command": "^2.0.0",
445 | "which": "^2.0.1"
446 | },
447 | "engines": {
448 | "node": ">= 8"
449 | }
450 | },
451 | "node_modules/electron-to-chromium": {
452 | "version": "1.5.13",
453 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz",
454 | "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==",
455 | "dev": true
456 | },
457 | "node_modules/enhanced-resolve": {
458 | "version": "5.17.1",
459 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
460 | "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
461 | "dev": true,
462 | "dependencies": {
463 | "graceful-fs": "^4.2.4",
464 | "tapable": "^2.2.0"
465 | },
466 | "engines": {
467 | "node": ">=10.13.0"
468 | }
469 | },
470 | "node_modules/envinfo": {
471 | "version": "7.13.0",
472 | "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz",
473 | "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==",
474 | "dev": true,
475 | "bin": {
476 | "envinfo": "dist/cli.js"
477 | },
478 | "engines": {
479 | "node": ">=4"
480 | }
481 | },
482 | "node_modules/es-module-lexer": {
483 | "version": "1.5.4",
484 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
485 | "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
486 | "dev": true
487 | },
488 | "node_modules/escalade": {
489 | "version": "3.2.0",
490 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
491 | "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
492 | "dev": true,
493 | "engines": {
494 | "node": ">=6"
495 | }
496 | },
497 | "node_modules/eslint-scope": {
498 | "version": "5.1.1",
499 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
500 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
501 | "dev": true,
502 | "dependencies": {
503 | "esrecurse": "^4.3.0",
504 | "estraverse": "^4.1.1"
505 | },
506 | "engines": {
507 | "node": ">=8.0.0"
508 | }
509 | },
510 | "node_modules/esrecurse": {
511 | "version": "4.3.0",
512 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
513 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
514 | "dev": true,
515 | "dependencies": {
516 | "estraverse": "^5.2.0"
517 | },
518 | "engines": {
519 | "node": ">=4.0"
520 | }
521 | },
522 | "node_modules/esrecurse/node_modules/estraverse": {
523 | "version": "5.3.0",
524 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
525 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
526 | "dev": true,
527 | "engines": {
528 | "node": ">=4.0"
529 | }
530 | },
531 | "node_modules/estraverse": {
532 | "version": "4.3.0",
533 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
534 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
535 | "dev": true,
536 | "engines": {
537 | "node": ">=4.0"
538 | }
539 | },
540 | "node_modules/events": {
541 | "version": "3.3.0",
542 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
543 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
544 | "dev": true,
545 | "engines": {
546 | "node": ">=0.8.x"
547 | }
548 | },
549 | "node_modules/fast-deep-equal": {
550 | "version": "3.1.3",
551 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
552 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
553 | "dev": true
554 | },
555 | "node_modules/fast-json-stable-stringify": {
556 | "version": "2.1.0",
557 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
558 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
559 | "dev": true
560 | },
561 | "node_modules/fastest-levenshtein": {
562 | "version": "1.0.16",
563 | "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
564 | "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
565 | "dev": true,
566 | "engines": {
567 | "node": ">= 4.9.1"
568 | }
569 | },
570 | "node_modules/find-up": {
571 | "version": "4.1.0",
572 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
573 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
574 | "dev": true,
575 | "dependencies": {
576 | "locate-path": "^5.0.0",
577 | "path-exists": "^4.0.0"
578 | },
579 | "engines": {
580 | "node": ">=8"
581 | }
582 | },
583 | "node_modules/flat": {
584 | "version": "5.0.2",
585 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
586 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
587 | "dev": true,
588 | "bin": {
589 | "flat": "cli.js"
590 | }
591 | },
592 | "node_modules/function-bind": {
593 | "version": "1.1.2",
594 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
595 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
596 | "dev": true,
597 | "funding": {
598 | "url": "https://github.com/sponsors/ljharb"
599 | }
600 | },
601 | "node_modules/glob-to-regexp": {
602 | "version": "0.4.1",
603 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
604 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
605 | "dev": true
606 | },
607 | "node_modules/graceful-fs": {
608 | "version": "4.2.11",
609 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
610 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
611 | "dev": true
612 | },
613 | "node_modules/has-flag": {
614 | "version": "4.0.0",
615 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
616 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
617 | "dev": true,
618 | "engines": {
619 | "node": ">=8"
620 | }
621 | },
622 | "node_modules/hasown": {
623 | "version": "2.0.2",
624 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
625 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
626 | "dev": true,
627 | "dependencies": {
628 | "function-bind": "^1.1.2"
629 | },
630 | "engines": {
631 | "node": ">= 0.4"
632 | }
633 | },
634 | "node_modules/import-local": {
635 | "version": "3.2.0",
636 | "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
637 | "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
638 | "dev": true,
639 | "dependencies": {
640 | "pkg-dir": "^4.2.0",
641 | "resolve-cwd": "^3.0.0"
642 | },
643 | "bin": {
644 | "import-local-fixture": "fixtures/cli.js"
645 | },
646 | "engines": {
647 | "node": ">=8"
648 | },
649 | "funding": {
650 | "url": "https://github.com/sponsors/sindresorhus"
651 | }
652 | },
653 | "node_modules/interpret": {
654 | "version": "2.2.0",
655 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
656 | "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
657 | "dev": true,
658 | "engines": {
659 | "node": ">= 0.10"
660 | }
661 | },
662 | "node_modules/is-core-module": {
663 | "version": "2.15.1",
664 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
665 | "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
666 | "dev": true,
667 | "dependencies": {
668 | "hasown": "^2.0.2"
669 | },
670 | "engines": {
671 | "node": ">= 0.4"
672 | },
673 | "funding": {
674 | "url": "https://github.com/sponsors/ljharb"
675 | }
676 | },
677 | "node_modules/is-plain-object": {
678 | "version": "2.0.4",
679 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
680 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
681 | "dev": true,
682 | "dependencies": {
683 | "isobject": "^3.0.1"
684 | },
685 | "engines": {
686 | "node": ">=0.10.0"
687 | }
688 | },
689 | "node_modules/isexe": {
690 | "version": "2.0.0",
691 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
692 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
693 | "dev": true
694 | },
695 | "node_modules/isobject": {
696 | "version": "3.0.1",
697 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
698 | "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
699 | "dev": true,
700 | "engines": {
701 | "node": ">=0.10.0"
702 | }
703 | },
704 | "node_modules/jest-worker": {
705 | "version": "27.5.1",
706 | "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
707 | "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
708 | "dev": true,
709 | "dependencies": {
710 | "@types/node": "*",
711 | "merge-stream": "^2.0.0",
712 | "supports-color": "^8.0.0"
713 | },
714 | "engines": {
715 | "node": ">= 10.13.0"
716 | }
717 | },
718 | "node_modules/json-parse-even-better-errors": {
719 | "version": "2.3.1",
720 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
721 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
722 | "dev": true
723 | },
724 | "node_modules/json-schema-traverse": {
725 | "version": "0.4.1",
726 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
727 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
728 | "dev": true
729 | },
730 | "node_modules/kind-of": {
731 | "version": "6.0.3",
732 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
733 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
734 | "dev": true,
735 | "engines": {
736 | "node": ">=0.10.0"
737 | }
738 | },
739 | "node_modules/loader-runner": {
740 | "version": "4.3.0",
741 | "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
742 | "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
743 | "dev": true,
744 | "engines": {
745 | "node": ">=6.11.5"
746 | }
747 | },
748 | "node_modules/locate-path": {
749 | "version": "5.0.0",
750 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
751 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
752 | "dev": true,
753 | "dependencies": {
754 | "p-locate": "^4.1.0"
755 | },
756 | "engines": {
757 | "node": ">=8"
758 | }
759 | },
760 | "node_modules/merge-stream": {
761 | "version": "2.0.0",
762 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
763 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
764 | "dev": true
765 | },
766 | "node_modules/mime-db": {
767 | "version": "1.52.0",
768 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
769 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
770 | "dev": true,
771 | "engines": {
772 | "node": ">= 0.6"
773 | }
774 | },
775 | "node_modules/mime-types": {
776 | "version": "2.1.35",
777 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
778 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
779 | "dev": true,
780 | "dependencies": {
781 | "mime-db": "1.52.0"
782 | },
783 | "engines": {
784 | "node": ">= 0.6"
785 | }
786 | },
787 | "node_modules/neo-async": {
788 | "version": "2.6.2",
789 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
790 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
791 | "dev": true
792 | },
793 | "node_modules/node-releases": {
794 | "version": "2.0.18",
795 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
796 | "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
797 | "dev": true
798 | },
799 | "node_modules/p-limit": {
800 | "version": "2.3.0",
801 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
802 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
803 | "dev": true,
804 | "dependencies": {
805 | "p-try": "^2.0.0"
806 | },
807 | "engines": {
808 | "node": ">=6"
809 | },
810 | "funding": {
811 | "url": "https://github.com/sponsors/sindresorhus"
812 | }
813 | },
814 | "node_modules/p-locate": {
815 | "version": "4.1.0",
816 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
817 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
818 | "dev": true,
819 | "dependencies": {
820 | "p-limit": "^2.2.0"
821 | },
822 | "engines": {
823 | "node": ">=8"
824 | }
825 | },
826 | "node_modules/p-try": {
827 | "version": "2.2.0",
828 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
829 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
830 | "dev": true,
831 | "engines": {
832 | "node": ">=6"
833 | }
834 | },
835 | "node_modules/path-exists": {
836 | "version": "4.0.0",
837 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
838 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
839 | "dev": true,
840 | "engines": {
841 | "node": ">=8"
842 | }
843 | },
844 | "node_modules/path-key": {
845 | "version": "3.1.1",
846 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
847 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
848 | "dev": true,
849 | "engines": {
850 | "node": ">=8"
851 | }
852 | },
853 | "node_modules/path-parse": {
854 | "version": "1.0.7",
855 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
856 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
857 | "dev": true
858 | },
859 | "node_modules/picocolors": {
860 | "version": "1.0.1",
861 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
862 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
863 | "dev": true
864 | },
865 | "node_modules/pkg-dir": {
866 | "version": "4.2.0",
867 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
868 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
869 | "dev": true,
870 | "dependencies": {
871 | "find-up": "^4.0.0"
872 | },
873 | "engines": {
874 | "node": ">=8"
875 | }
876 | },
877 | "node_modules/punycode": {
878 | "version": "2.3.1",
879 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
880 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
881 | "dev": true,
882 | "engines": {
883 | "node": ">=6"
884 | }
885 | },
886 | "node_modules/randombytes": {
887 | "version": "2.1.0",
888 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
889 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
890 | "dev": true,
891 | "dependencies": {
892 | "safe-buffer": "^5.1.0"
893 | }
894 | },
895 | "node_modules/rechoir": {
896 | "version": "0.7.1",
897 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
898 | "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
899 | "dev": true,
900 | "dependencies": {
901 | "resolve": "^1.9.0"
902 | },
903 | "engines": {
904 | "node": ">= 0.10"
905 | }
906 | },
907 | "node_modules/resolve": {
908 | "version": "1.22.8",
909 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
910 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
911 | "dev": true,
912 | "dependencies": {
913 | "is-core-module": "^2.13.0",
914 | "path-parse": "^1.0.7",
915 | "supports-preserve-symlinks-flag": "^1.0.0"
916 | },
917 | "bin": {
918 | "resolve": "bin/resolve"
919 | },
920 | "funding": {
921 | "url": "https://github.com/sponsors/ljharb"
922 | }
923 | },
924 | "node_modules/resolve-cwd": {
925 | "version": "3.0.0",
926 | "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
927 | "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
928 | "dev": true,
929 | "dependencies": {
930 | "resolve-from": "^5.0.0"
931 | },
932 | "engines": {
933 | "node": ">=8"
934 | }
935 | },
936 | "node_modules/resolve-from": {
937 | "version": "5.0.0",
938 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
939 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
940 | "dev": true,
941 | "engines": {
942 | "node": ">=8"
943 | }
944 | },
945 | "node_modules/safe-buffer": {
946 | "version": "5.2.1",
947 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
948 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
949 | "dev": true,
950 | "funding": [
951 | {
952 | "type": "github",
953 | "url": "https://github.com/sponsors/feross"
954 | },
955 | {
956 | "type": "patreon",
957 | "url": "https://www.patreon.com/feross"
958 | },
959 | {
960 | "type": "consulting",
961 | "url": "https://feross.org/support"
962 | }
963 | ]
964 | },
965 | "node_modules/schema-utils": {
966 | "version": "3.3.0",
967 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
968 | "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
969 | "dev": true,
970 | "dependencies": {
971 | "@types/json-schema": "^7.0.8",
972 | "ajv": "^6.12.5",
973 | "ajv-keywords": "^3.5.2"
974 | },
975 | "engines": {
976 | "node": ">= 10.13.0"
977 | },
978 | "funding": {
979 | "type": "opencollective",
980 | "url": "https://opencollective.com/webpack"
981 | }
982 | },
983 | "node_modules/serialize-javascript": {
984 | "version": "6.0.2",
985 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
986 | "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
987 | "dev": true,
988 | "dependencies": {
989 | "randombytes": "^2.1.0"
990 | }
991 | },
992 | "node_modules/shallow-clone": {
993 | "version": "3.0.1",
994 | "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
995 | "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
996 | "dev": true,
997 | "dependencies": {
998 | "kind-of": "^6.0.2"
999 | },
1000 | "engines": {
1001 | "node": ">=8"
1002 | }
1003 | },
1004 | "node_modules/shebang-command": {
1005 | "version": "2.0.0",
1006 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1007 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1008 | "dev": true,
1009 | "dependencies": {
1010 | "shebang-regex": "^3.0.0"
1011 | },
1012 | "engines": {
1013 | "node": ">=8"
1014 | }
1015 | },
1016 | "node_modules/shebang-regex": {
1017 | "version": "3.0.0",
1018 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1019 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1020 | "dev": true,
1021 | "engines": {
1022 | "node": ">=8"
1023 | }
1024 | },
1025 | "node_modules/source-map": {
1026 | "version": "0.6.1",
1027 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1028 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
1029 | "dev": true,
1030 | "engines": {
1031 | "node": ">=0.10.0"
1032 | }
1033 | },
1034 | "node_modules/source-map-support": {
1035 | "version": "0.5.21",
1036 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
1037 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
1038 | "dev": true,
1039 | "dependencies": {
1040 | "buffer-from": "^1.0.0",
1041 | "source-map": "^0.6.0"
1042 | }
1043 | },
1044 | "node_modules/supports-color": {
1045 | "version": "8.1.1",
1046 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
1047 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
1048 | "dev": true,
1049 | "dependencies": {
1050 | "has-flag": "^4.0.0"
1051 | },
1052 | "engines": {
1053 | "node": ">=10"
1054 | },
1055 | "funding": {
1056 | "url": "https://github.com/chalk/supports-color?sponsor=1"
1057 | }
1058 | },
1059 | "node_modules/supports-preserve-symlinks-flag": {
1060 | "version": "1.0.0",
1061 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1062 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1063 | "dev": true,
1064 | "engines": {
1065 | "node": ">= 0.4"
1066 | },
1067 | "funding": {
1068 | "url": "https://github.com/sponsors/ljharb"
1069 | }
1070 | },
1071 | "node_modules/tapable": {
1072 | "version": "2.2.1",
1073 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
1074 | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
1075 | "dev": true,
1076 | "engines": {
1077 | "node": ">=6"
1078 | }
1079 | },
1080 | "node_modules/terser": {
1081 | "version": "5.31.6",
1082 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz",
1083 | "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==",
1084 | "dev": true,
1085 | "dependencies": {
1086 | "@jridgewell/source-map": "^0.3.3",
1087 | "acorn": "^8.8.2",
1088 | "commander": "^2.20.0",
1089 | "source-map-support": "~0.5.20"
1090 | },
1091 | "bin": {
1092 | "terser": "bin/terser"
1093 | },
1094 | "engines": {
1095 | "node": ">=10"
1096 | }
1097 | },
1098 | "node_modules/terser-webpack-plugin": {
1099 | "version": "5.3.10",
1100 | "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
1101 | "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
1102 | "dev": true,
1103 | "dependencies": {
1104 | "@jridgewell/trace-mapping": "^0.3.20",
1105 | "jest-worker": "^27.4.5",
1106 | "schema-utils": "^3.1.1",
1107 | "serialize-javascript": "^6.0.1",
1108 | "terser": "^5.26.0"
1109 | },
1110 | "engines": {
1111 | "node": ">= 10.13.0"
1112 | },
1113 | "funding": {
1114 | "type": "opencollective",
1115 | "url": "https://opencollective.com/webpack"
1116 | },
1117 | "peerDependencies": {
1118 | "webpack": "^5.1.0"
1119 | },
1120 | "peerDependenciesMeta": {
1121 | "@swc/core": {
1122 | "optional": true
1123 | },
1124 | "esbuild": {
1125 | "optional": true
1126 | },
1127 | "uglify-js": {
1128 | "optional": true
1129 | }
1130 | }
1131 | },
1132 | "node_modules/undici-types": {
1133 | "version": "6.19.8",
1134 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
1135 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
1136 | "dev": true
1137 | },
1138 | "node_modules/update-browserslist-db": {
1139 | "version": "1.1.0",
1140 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
1141 | "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
1142 | "dev": true,
1143 | "funding": [
1144 | {
1145 | "type": "opencollective",
1146 | "url": "https://opencollective.com/browserslist"
1147 | },
1148 | {
1149 | "type": "tidelift",
1150 | "url": "https://tidelift.com/funding/github/npm/browserslist"
1151 | },
1152 | {
1153 | "type": "github",
1154 | "url": "https://github.com/sponsors/ai"
1155 | }
1156 | ],
1157 | "dependencies": {
1158 | "escalade": "^3.1.2",
1159 | "picocolors": "^1.0.1"
1160 | },
1161 | "bin": {
1162 | "update-browserslist-db": "cli.js"
1163 | },
1164 | "peerDependencies": {
1165 | "browserslist": ">= 4.21.0"
1166 | }
1167 | },
1168 | "node_modules/uri-js": {
1169 | "version": "4.4.1",
1170 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
1171 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
1172 | "dev": true,
1173 | "dependencies": {
1174 | "punycode": "^2.1.0"
1175 | }
1176 | },
1177 | "node_modules/watchpack": {
1178 | "version": "2.4.2",
1179 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
1180 | "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
1181 | "dev": true,
1182 | "dependencies": {
1183 | "glob-to-regexp": "^0.4.1",
1184 | "graceful-fs": "^4.1.2"
1185 | },
1186 | "engines": {
1187 | "node": ">=10.13.0"
1188 | }
1189 | },
1190 | "node_modules/webpack": {
1191 | "version": "5.94.0",
1192 | "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
1193 | "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
1194 | "dev": true,
1195 | "dependencies": {
1196 | "@types/estree": "^1.0.5",
1197 | "@webassemblyjs/ast": "^1.12.1",
1198 | "@webassemblyjs/wasm-edit": "^1.12.1",
1199 | "@webassemblyjs/wasm-parser": "^1.12.1",
1200 | "acorn": "^8.7.1",
1201 | "acorn-import-attributes": "^1.9.5",
1202 | "browserslist": "^4.21.10",
1203 | "chrome-trace-event": "^1.0.2",
1204 | "enhanced-resolve": "^5.17.1",
1205 | "es-module-lexer": "^1.2.1",
1206 | "eslint-scope": "5.1.1",
1207 | "events": "^3.2.0",
1208 | "glob-to-regexp": "^0.4.1",
1209 | "graceful-fs": "^4.2.11",
1210 | "json-parse-even-better-errors": "^2.3.1",
1211 | "loader-runner": "^4.2.0",
1212 | "mime-types": "^2.1.27",
1213 | "neo-async": "^2.6.2",
1214 | "schema-utils": "^3.2.0",
1215 | "tapable": "^2.1.1",
1216 | "terser-webpack-plugin": "^5.3.10",
1217 | "watchpack": "^2.4.1",
1218 | "webpack-sources": "^3.2.3"
1219 | },
1220 | "bin": {
1221 | "webpack": "bin/webpack.js"
1222 | },
1223 | "engines": {
1224 | "node": ">=10.13.0"
1225 | },
1226 | "funding": {
1227 | "type": "opencollective",
1228 | "url": "https://opencollective.com/webpack"
1229 | },
1230 | "peerDependenciesMeta": {
1231 | "webpack-cli": {
1232 | "optional": true
1233 | }
1234 | }
1235 | },
1236 | "node_modules/webpack-cli": {
1237 | "version": "4.10.0",
1238 | "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
1239 | "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
1240 | "dev": true,
1241 | "dependencies": {
1242 | "@discoveryjs/json-ext": "^0.5.0",
1243 | "@webpack-cli/configtest": "^1.2.0",
1244 | "@webpack-cli/info": "^1.5.0",
1245 | "@webpack-cli/serve": "^1.7.0",
1246 | "colorette": "^2.0.14",
1247 | "commander": "^7.0.0",
1248 | "cross-spawn": "^7.0.3",
1249 | "fastest-levenshtein": "^1.0.12",
1250 | "import-local": "^3.0.2",
1251 | "interpret": "^2.2.0",
1252 | "rechoir": "^0.7.0",
1253 | "webpack-merge": "^5.7.3"
1254 | },
1255 | "bin": {
1256 | "webpack-cli": "bin/cli.js"
1257 | },
1258 | "engines": {
1259 | "node": ">=10.13.0"
1260 | },
1261 | "funding": {
1262 | "type": "opencollective",
1263 | "url": "https://opencollective.com/webpack"
1264 | },
1265 | "peerDependencies": {
1266 | "webpack": "4.x.x || 5.x.x"
1267 | },
1268 | "peerDependenciesMeta": {
1269 | "@webpack-cli/generators": {
1270 | "optional": true
1271 | },
1272 | "@webpack-cli/migrate": {
1273 | "optional": true
1274 | },
1275 | "webpack-bundle-analyzer": {
1276 | "optional": true
1277 | },
1278 | "webpack-dev-server": {
1279 | "optional": true
1280 | }
1281 | }
1282 | },
1283 | "node_modules/webpack-cli/node_modules/commander": {
1284 | "version": "7.2.0",
1285 | "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
1286 | "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
1287 | "dev": true,
1288 | "engines": {
1289 | "node": ">= 10"
1290 | }
1291 | },
1292 | "node_modules/webpack-merge": {
1293 | "version": "5.10.0",
1294 | "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
1295 | "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
1296 | "dev": true,
1297 | "dependencies": {
1298 | "clone-deep": "^4.0.1",
1299 | "flat": "^5.0.2",
1300 | "wildcard": "^2.0.0"
1301 | },
1302 | "engines": {
1303 | "node": ">=10.0.0"
1304 | }
1305 | },
1306 | "node_modules/webpack-sources": {
1307 | "version": "3.2.3",
1308 | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
1309 | "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
1310 | "dev": true,
1311 | "engines": {
1312 | "node": ">=10.13.0"
1313 | }
1314 | },
1315 | "node_modules/which": {
1316 | "version": "2.0.2",
1317 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1318 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1319 | "dev": true,
1320 | "dependencies": {
1321 | "isexe": "^2.0.0"
1322 | },
1323 | "bin": {
1324 | "node-which": "bin/node-which"
1325 | },
1326 | "engines": {
1327 | "node": ">= 8"
1328 | }
1329 | },
1330 | "node_modules/wildcard": {
1331 | "version": "2.0.1",
1332 | "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
1333 | "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
1334 | "dev": true
1335 | }
1336 | }
1337 | }
1338 |
--------------------------------------------------------------------------------
/browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "main": "../src/index.js",
5 | "author": "herumi (https://github.com/herumi/)",
6 | "license": "BSD-3-Clause",
7 | "devDependencies": {
8 | "webpack": "^5.37.0",
9 | "webpack-cli": "^4.7.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/browser/readme.md:
--------------------------------------------------------------------------------
1 | # browser demo
2 |
3 | How to build `browser/bls.js`.
4 | ```
5 | cd browser
6 | npm install webpack webpack-cli --save-dev
7 | npx webpack
8 | python3 -m http.server
9 | ```
10 |
11 |
--------------------------------------------------------------------------------
/browser/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | entry: "../src/index.js",
3 | mode: "production",
4 | output: {
5 | path: __dirname + '/',
6 | library: 'bls',
7 | libraryTarget: 'umd',
8 | filename: 'bls.js'
9 | },
10 | /*
11 | resolve: {
12 | fallback: {
13 | path: false,
14 | fs: false,
15 | crypto: false,
16 | },
17 | },
18 | */
19 | target: "web"
20 | };
21 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bls-eth-wasm",
3 | "version": "1.4.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "bls-eth-wasm",
9 | "version": "1.4.0",
10 | "license": "BSD-3-Clause"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bls-eth-wasm",
3 | "version": "1.4.0",
4 | "description": "BLS signature for Node.js by WebAssembly for Ethereum 2.0",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "node test/test.js"
8 | },
9 | "types": "src/index.d.ts",
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/herumi/bls-eth-wasm.git"
13 | },
14 | "keywords": [
15 | "BLS signature",
16 | "WebAssembly",
17 | "pairing"
18 | ],
19 | "files": [
20 | "package.json",
21 | "src/index.js",
22 | "src/bls.js",
23 | "src/bls_c.js",
24 | "src/index.d.ts",
25 | "browser/bls.js",
26 | "browser/package.json"
27 | ],
28 | "author": "herumi (https://github.com/herumi/)",
29 | "license": "BSD-3-Clause",
30 | "bugs": {
31 | "url": "https://github.com/herumi/bls-eth-wasm/issues"
32 | },
33 | "homepage": "https://github.com/herumi/bls-eth-wasm#readme"
34 | }
35 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/herumi/bls-eth-wasm/actions/workflows/main.yml)
2 |
3 | # BLS signature for Node.js by WebAssembly
4 |
5 | # Abstract
6 | This module is built with `BLS_ETH=1` for Ethereum 2.0 spec.
7 |
8 | # News
9 | - 2024/Sep/18 : About 10% performance improvement
10 | - 2022/Jul/20 : 1.1 times improved
11 | - 2021/Aug/28 : improve performance of `{G1,G2}::isValidOrder()`
12 | - 2020/Nov/04 : break backward compatibility (bls.js is renamed to index.js)
13 | - use blsSetupFactory to make bls instance on browser (see the top of bls-demo.js)
14 | - 2020/Oct/01 : add `bls.multiVerify` to verify all {sigs, pubs, msgs}.
15 | - 2020/Jul/06 ; `setETHmode(bls.ETH_MODE_DRAFT_07)` is default mode
16 |
17 | ## How to use
18 | The version `v0.4.2` breaks backward compatibility of the entry point.
19 |
20 | - Node.js : `const bls = require('bls-eth-wasm')`
21 | - React : `const bls = require('bls-eth-wasm/browser')`
22 | - HTML : ``
23 |
24 | Init as the followings:
25 |
26 | ```
27 | bls.init(bls.BLS12_381)
28 | ```
29 |
30 | (old) The new [eth2.0 functions](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#bls-signatures) are supported. This mode will be removed in the future.
31 |
32 | Init as the followings:
33 |
34 | ```
35 | bls.init(bls.BLS12_381)
36 | ```
37 |
38 | then, you can use the following functions.
39 |
40 | bls-eth-wasm | eth2.0 spec name|
41 | ------|-----------------|
42 | SecretKey::sign|Sign|
43 | PublicKey::verify|Verify|
44 | Sign::aggregate|Aggregate|
45 | Sign::fastAggregateVerify|FastAggregateVerify|
46 | Sign::aggregateVerifyNoCheck|AggregateVerify|
47 |
48 | The size of message must be 32 byte.
49 |
50 | Check functions:
51 | - verifySignatureOrder ; make `deserialize` check the correctness of the order
52 | - Sign::isValidOrder ; check the correctness of the order
53 | - verifyPublicKeyOrder ; make `deserialize` check the correctness of the order
54 | - PublicKey::isValidOrder ; check the correctness of the order
55 | - areAllMsgDifferent ; check that all messages are different each other
56 |
57 | see [bls](https://github.com/herumi/bls)
58 |
59 | ## How to build src/bls_c.js
60 | Install [Emscripten](https://emscripten.org/).
61 | ```
62 | cd src
63 | git submodule update --init
64 | make
65 | ```
66 |
67 | ## For Node.js
68 | node test.js
69 |
70 | ## Browser demo
71 |
72 | see [bls-demo](https://herumi.github.io/bls-eth-wasm/browser/demo.html).
73 |
74 | See `browser/readme.md` to make `browser/bls.js`.
75 |
76 | ## for React
77 |
78 | ```
79 | const bls = require('bls-eth-wasm/browser')
80 | ```
81 |
82 | # License
83 |
84 | modified new BSD License
85 | http://opensource.org/licenses/BSD-3-Clause
86 |
87 | # Author
88 |
89 | MITSUNARI Shigeo(herumi@nifty.com)
90 |
91 | # Sponsors welcome
92 | [GitHub Sponsor](https://github.com/sponsors/herumi)
93 |
--------------------------------------------------------------------------------
/src/Makefile:
--------------------------------------------------------------------------------
1 | all: bls_c.js
2 | BLS_DIR?=./bls
3 | MCL_DIR?=$(BLS_DIR)/mcl
4 |
5 | EMCC_OPT=-I $(BLS_DIR)/include -I $(MCL_DIR)/src -I $(MCL_DIR)/include -I./bls
6 | EMCC_OPT+=-DBLS_ETH
7 | EMCC_OPT+=-Wall -Wextra
8 | EMCC_OPT+=-O3 -DNDEBUG
9 | EMCC_OPT+=-DMCL_SIZEOF_UNIT=4
10 | EMCC_OPT+=-std=c++03 -fno-threadsafe-statics -fno-rtti -fno-stack-protector
11 | EMCC_OPT+=-flto
12 | EMCC_OPT+=-fno-exceptions
13 | EMCC_OPT+=-DMCLBN_FORCE_EXPORT
14 | EMCC_OPT+=-DMCL_MAX_BIT_SIZE=384
15 | EMCC_OPT+=-DCYBOZU_MINIMUM_EXCEPTION -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -DMCL_DONT_USE_CSPRNG
16 | EMCC_OPT+=-DMCL_USE_WEB_CRYPTO_API
17 | EMCC_OPT+=-s WASM=1
18 | EMCC_OPT+=-s NO_EXIT_RUNTIME=1
19 | EMCC_OPT+=-s NODEJS_CATCH_EXIT=0
20 | EMCC_OPT+=-s NODEJS_CATCH_REJECTION=0
21 | #EMCC_OPT+=-s ASSERTIONS=1
22 | EMCC_OPT+=-s MODULARIZE=1
23 | #EMCC_OPT+=-s EXPORT_NAME='blsCreateModule'
24 | #EMCC_OPT+=-s STRICT_JS=1
25 | EMCC_OPT+=-s SINGLE_FILE=1
26 | #EMCC_OPT+=-s MINIFY_HTML=0
27 | EMCC_OPT+=--minify 0
28 | EMCC_OPT+=-s ABORTING_MALLOC=0
29 | EMCC_OPT+=-s DISABLE_EXCEPTION_CATCHING=1
30 | EMCC_OPT+=-s STACK_SIZE=1MB
31 |
32 | bls_c.js:
33 | emcc -o $@ $(BLS_DIR)/src/bls_c384_256.cpp $(MCL_DIR)/src/fp.cpp $(EMCC_OPT)
34 | # disable require fs, path
35 | perl -i -pe 's@(.* = require\(.*)@//\1@' $@
36 |
37 | clean:
38 | rm -rf bls_c.js
39 |
40 | .PHONY: clean bls_c.js
41 |
42 |
--------------------------------------------------------------------------------
/src/bls.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param createModule Async factory that returns an emcc initialized Module
3 | * In node, `const createModule = require(`./bls_c.js`)`
4 | */
5 | const ETH_MODE = true
6 |
7 | const _blsSetupFactory = (createModule) => {
8 | const exports = {}
9 | /* eslint-disable */
10 | exports.BN254 = 0
11 | exports.BN381_1 = 1
12 | exports.BN_SNARK1 = 4
13 | exports.BLS12_381 = 5
14 | exports.ethMode = ETH_MODE
15 | exports.ETH_MODE_DRAFT_05 = 1
16 | exports.ETH_MODE_DRAFT_06 = 2
17 | exports.ETH_MODE_DRAFT_07 = 3
18 | exports.MAP_TO_MODE_ORIGINAL = 0
19 | exports.MAP_TO_MODE_HASH_TO_CURVE = 5 // IRTF
20 |
21 | function blsSetup(exports, curveType) {
22 | const mod = exports.mod
23 | const MCLBN_FP_UNIT_SIZE = 6
24 | const MCLBN_FP_SIZE = MCLBN_FP_UNIT_SIZE * 8
25 | const MCLBN_FR_UNIT_SIZE = 4
26 | const MCLBN_FR_SIZE = MCLBN_FR_UNIT_SIZE * 8
27 | const BLS_COMPILER_TIME_VAR_ADJ = exports.ethMode ? 200 : 0
28 | const MCLBN_COMPILED_TIME_VAR = (MCLBN_FR_UNIT_SIZE * 10 + MCLBN_FP_UNIT_SIZE) + BLS_COMPILER_TIME_VAR_ADJ
29 | const BLS_ID_SIZE = MCLBN_FR_SIZE
30 | const BLS_SECRETKEY_SIZE = MCLBN_FR_SIZE
31 | const BLS_PUBLICKEY_SIZE = MCLBN_FP_SIZE * 3 * (exports.ethMode ? 1 : 2)
32 | const BLS_SIGNATURE_SIZE = MCLBN_FP_SIZE * 3 * (exports.ethMode ? 2 : 1)
33 |
34 | const _malloc = size => {
35 | return mod._blsMalloc(size)
36 | }
37 | const _free = pos => {
38 | mod._blsFree(pos)
39 | }
40 | const ptrToAsciiStr = (pos, n) => {
41 | let s = ''
42 | for (let i = 0; i < n; i++) {
43 | s += String.fromCharCode(mod.HEAP8[pos + i])
44 | }
45 | return s
46 | }
47 | const asciiStrToPtr = (pos, s) => {
48 | for (let i = 0; i < s.length; i++) {
49 | mod.HEAP8[pos + i] = s.charCodeAt(i)
50 | }
51 | }
52 | exports.toHex = (a, start, n) => {
53 | let s = ''
54 | for (let i = 0; i < n; i++) {
55 | s += ('0' + a[start + i].toString(16)).slice(-2)
56 | }
57 | return s
58 | }
59 | // Uint8Array to hex string
60 | exports.toHexStr = a => {
61 | return exports.toHex(a, 0, a.length)
62 | }
63 | // hex string to Uint8Array
64 | exports.fromHexStr = s => {
65 | if (s.length & 1) throw new Error('fromHexStr:length must be even ' + s.length)
66 | const n = s.length / 2
67 | const a = new Uint8Array(n)
68 | for (let i = 0; i < n; i++) {
69 | a[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16)
70 | }
71 | return a
72 | }
73 | ///////////////////////////
74 | const copyToUint32Array = (a, pos) => {
75 | a.set(mod.HEAP32.subarray(pos / 4, pos / 4 + a.length))
76 | // for (let i = 0; i < a.length; i++) {
77 | // a[i] = mod.HEAP32[pos / 4 + i]
78 | // }
79 | }
80 | const copyFromUint32Array = (pos, a) => {
81 | mod.HEAP32.set(a, pos / 4)
82 | // for (let i = 0; i < a.length; i++) {
83 | // mod.HEAP32[pos / 4 + i] = a[i]
84 | // }
85 | }
86 | //////////////////////////////////
87 | const _wrapGetStr = (func, returnAsStr = true) => {
88 | return (x, ioMode = 0) => {
89 | const maxBufSize = 3096
90 | const pos = _malloc(maxBufSize)
91 | const n = func(pos, maxBufSize, x, ioMode)
92 | if (n <= 0) {
93 | throw new Error('err gen_str:' + x)
94 | }
95 | let s = null
96 | if (returnAsStr) {
97 | s = ptrToAsciiStr(pos, n)
98 | } else {
99 | s = new Uint8Array(mod.HEAP8.subarray(pos, pos + n))
100 | }
101 | _free(pos)
102 | return s
103 | }
104 | }
105 | const _wrapSerialize = func => {
106 | return _wrapGetStr(func, false)
107 | }
108 | const _wrapDeserialize = func => {
109 | return (x, buf) => {
110 | const pos = _malloc(buf.length)
111 | mod.HEAP8.set(buf, pos)
112 | const r = func(x, pos, buf.length)
113 | _free(pos)
114 | if (r === 0 || r !== buf.length) throw new Error('err _wrapDeserialize', buf)
115 | }
116 | }
117 | /*
118 | argNum : n
119 | func(x0, ..., x_(n-1), buf, ioMode)
120 | => func(x0, ..., x_(n-1), pos, buf.length, ioMode)
121 | */
122 | const _wrapInput = (func, argNum, returnValue = false) => {
123 | return function () {
124 | const args = [...arguments]
125 | const buf = args[argNum]
126 | const typeStr = Object.prototype.toString.apply(buf)
127 | if (['[object String]', '[object Uint8Array]', '[object Array]'].indexOf(typeStr) < 0) {
128 | throw new Error(`err bad type:"${typeStr}". Use String or Uint8Array.`)
129 | }
130 | const ioMode = args[argNum + 1] // may undefined
131 | const pos = _malloc(buf.length)
132 | if (typeStr === '[object String]') {
133 | asciiStrToPtr(pos, buf)
134 | } else {
135 | mod.HEAP8.set(buf, pos)
136 | }
137 | const r = func(...args.slice(0, argNum), pos, buf.length, ioMode)
138 | _free(pos)
139 | if (returnValue) return r
140 | if (r) throw new Error('err _wrapInput ' + buf)
141 | }
142 | }
143 | const callSetter = (func, a, p1, p2) => {
144 | const pos = _malloc(a.length * 4)
145 | func(pos, p1, p2) // p1, p2 may be undefined
146 | copyToUint32Array(a, pos)
147 | _free(pos)
148 | }
149 | const callGetter = (func, a, p1, p2) => {
150 | const pos = _malloc(a.length * 4)
151 | mod.HEAP32.set(a, pos / 4)
152 | const s = func(pos, p1, p2)
153 | _free(pos)
154 | return s
155 | }
156 | const callShare = (func, a, size, vec, id) => {
157 | const pos = a._allocAndCopy()
158 | const idPos = id._allocAndCopy()
159 | const vecPos = _malloc(size * vec.length)
160 | for (let i = 0; i < vec.length; i++) {
161 | copyFromUint32Array(vecPos + size * i, vec[i].a_)
162 | }
163 | func(pos, vecPos, vec.length, idPos)
164 | _free(vecPos)
165 | _free(idPos)
166 | a._saveAndFree(pos)
167 | }
168 | const callRecover = (func, a, size, vec, idVec) => {
169 | const n = vec.length
170 | if (n != idVec.length) throw ('recover:bad length')
171 | const secPos = a._alloc()
172 | const vecPos = _malloc(size * n)
173 | const idVecPos = _malloc(BLS_ID_SIZE * n)
174 | for (let i = 0; i < n; i++) {
175 | copyFromUint32Array(vecPos + size * i, vec[i].a_)
176 | copyFromUint32Array(idVecPos + BLS_ID_SIZE * i, idVec[i].a_)
177 | }
178 | const r = func(secPos, vecPos, idVecPos, n)
179 | _free(idVecPos)
180 | _free(vecPos)
181 | a._saveAndFree(secPos)
182 | if (r) throw ('callRecover')
183 | }
184 |
185 | // change curveType
186 | exports.blsInit = (curveType = exports.ethMode ? exports.BLS12_381 : exports.BN254) => {
187 | const r = mod._blsInit(curveType, MCLBN_COMPILED_TIME_VAR)
188 | if (r) throw ('blsInit err ' + r)
189 | }
190 | exports.mclBnFr_setLittleEndian = _wrapInput(mod._mclBnFr_setLittleEndian, 1)
191 | exports.mclBnFr_setLittleEndianMod = _wrapInput(mod._mclBnFr_setLittleEndianMod, 1)
192 | exports.mclBnFr_setBigEndianMod = _wrapInput(mod._mclBnFr_setBigEndianMod, 1)
193 | exports.mclBnFr_setStr = _wrapInput(mod._mclBnFr_setStr, 1)
194 | exports.mclBnFr_getStr = _wrapGetStr(mod._mclBnFr_getStr)
195 | exports.mclBnFr_deserialize = _wrapDeserialize(mod._mclBnFr_deserialize)
196 | exports.mclBnFr_serialize = _wrapSerialize(mod._mclBnFr_serialize)
197 | exports.mclBnFr_setHashOf = _wrapInput(mod._mclBnFr_setHashOf, 1)
198 |
199 | exports.mclBnG1_setStr = _wrapInput(mod._mclBnG1_setStr, 1)
200 | exports.mclBnG1_getStr = _wrapGetStr(mod._mclBnG1_getStr)
201 | exports.mclBnG2_setStr = _wrapInput(mod._mclBnG2_setStr, 1)
202 | exports.mclBnG2_getStr = _wrapGetStr(mod._mclBnG2_getStr)
203 |
204 | exports.getCurveOrder = _wrapGetStr(mod._blsGetCurveOrder)
205 | exports.getFieldOrder = _wrapGetStr(mod._blsGetFieldOrder)
206 | exports.setDstG1 = _wrapInput(mod._mclBnG1_setDst, 0)
207 | exports.setDstG2 = _wrapInput(mod._mclBnG2_setDst, 0)
208 |
209 | exports.blsIdSetDecStr = _wrapInput(mod._blsIdSetDecStr, 1)
210 | exports.blsIdSetHexStr = _wrapInput(mod._blsIdSetHexStr, 1)
211 | exports.blsIdGetDecStr = _wrapGetStr(mod._blsIdGetDecStr)
212 | exports.blsIdGetHexStr = _wrapGetStr(mod._blsIdGetHexStr)
213 |
214 | exports.blsIdSerialize = _wrapSerialize(mod._blsIdSerialize)
215 | exports.blsSecretKeySerialize = _wrapSerialize(mod._blsSecretKeySerialize)
216 | exports.blsPublicKeySerialize = _wrapSerialize(mod._blsPublicKeySerialize)
217 | exports.blsSignatureSerialize = _wrapSerialize(mod._blsSignatureSerialize)
218 |
219 | exports.blsIdDeserialize = _wrapDeserialize(mod._blsIdDeserialize)
220 | exports.blsSecretKeyDeserialize = _wrapDeserialize(mod._blsSecretKeyDeserialize)
221 | exports.blsPublicKeyDeserialize = _wrapDeserialize(mod._blsPublicKeyDeserialize)
222 | exports.blsSignatureDeserialize = _wrapDeserialize(mod._blsSignatureDeserialize)
223 |
224 | exports.blsPublicKeySerializeUncompressed = _wrapSerialize(mod._blsPublicKeySerializeUncompressed)
225 | exports.blsSignatureSerializeUncompressed = _wrapSerialize(mod._blsSignatureSerializeUncompressed)
226 | exports.blsPublicKeyDeserializeUncompressed = _wrapDeserialize(mod._blsPublicKeyDeserializeUncompressed)
227 | exports.blsSignatureDeserializeUncompressed = _wrapDeserialize(mod._blsSignatureDeserializeUncompressed)
228 |
229 | exports.blsSecretKeySetLittleEndian = _wrapInput(mod._blsSecretKeySetLittleEndian, 1)
230 | exports.blsSecretKeySetLittleEndianMod = _wrapInput(mod._blsSecretKeySetLittleEndianMod, 1)
231 | exports.blsHashToSecretKey = _wrapInput(mod._blsHashToSecretKey, 1)
232 | exports.blsSign = _wrapInput(mod._blsSign, 2)
233 | exports.blsVerify = _wrapInput(mod._blsVerify, 2, true)
234 |
235 | class Common {
236 | constructor (size) {
237 | this.a_ = new Uint32Array(size / 4)
238 | }
239 | deserializeHexStr (s) {
240 | this.deserialize(exports.fromHexStr(s))
241 | }
242 | serializeToHexStr () {
243 | return exports.toHexStr(this.serialize())
244 | }
245 | dump (msg = '') {
246 | console.log(msg + this.serializeToHexStr())
247 | }
248 | clear () {
249 | this.a_.fill(0)
250 | }
251 | clone () {
252 | const copy = new this.constructor()
253 | copy.a_ = this.a_.slice(0)
254 | return copy
255 | }
256 | // alloc new array
257 | _alloc () {
258 | return _malloc(this.a_.length * 4)
259 | }
260 | // alloc and copy a_ to mod.HEAP32[pos / 4]
261 | _allocAndCopy () {
262 | const pos = this._alloc()
263 | mod.HEAP32.set(this.a_, pos / 4)
264 | return pos
265 | }
266 | // save pos to a_
267 | _save (pos) {
268 | this.a_.set(mod.HEAP32.subarray(pos / 4, pos / 4 + this.a_.length))
269 | }
270 | // save and free
271 | _saveAndFree(pos) {
272 | this._save(pos)
273 | _free(pos)
274 | }
275 | // set parameter (p1, p2 may be undefined)
276 | _setter (func, p1, p2) {
277 | const pos = this._alloc()
278 | const r = func(pos, p1, p2)
279 | this._saveAndFree(pos)
280 | if (r) throw new Error('_setter err')
281 | }
282 | // getter (p1, p2 may be undefined)
283 | _getter (func, p1, p2) {
284 | const pos = this._allocAndCopy()
285 | const s = func(pos, p1, p2)
286 | _free(pos)
287 | return s
288 | }
289 | _isEqual (func, rhs) {
290 | const xPos = this._allocAndCopy()
291 | const yPos = rhs._allocAndCopy()
292 | const r = func(xPos, yPos)
293 | _free(yPos)
294 | _free(xPos)
295 | return r === 1
296 | }
297 | // func(y, this) and return y
298 | _op1 (func) {
299 | const y = new this.constructor()
300 | const xPos = this._allocAndCopy()
301 | const yPos = y._alloc()
302 | func(yPos, xPos)
303 | y._saveAndFree(yPos)
304 | _free(xPos)
305 | return y
306 | }
307 | // func(z, this, y) and return z
308 | _op2 (func, y, Cstr = null) {
309 | const z = Cstr ? new Cstr() : new this.constructor()
310 | const xPos = this._allocAndCopy()
311 | const yPos = y._allocAndCopy()
312 | const zPos = z._alloc()
313 | func(zPos, xPos, yPos)
314 | z._saveAndFree(zPos)
315 | _free(yPos)
316 | _free(xPos)
317 | return z
318 | }
319 | // func(self, y)
320 | _update (func, y) {
321 | const xPos = this._allocAndCopy()
322 | const yPos = y._allocAndCopy()
323 | func(xPos, yPos)
324 | _free(yPos)
325 | this._saveAndFree(xPos)
326 | }
327 | }
328 |
329 | exports.Fr = class extends Common {
330 | constructor () {
331 | super(MCLBN_FR_SIZE)
332 | }
333 | setInt (x) {
334 | this._setter(mod._mclBnFr_setInt32, x)
335 | }
336 | deserialize (s) {
337 | this._setter(exports.mclBnFr_deserialize, s)
338 | }
339 | serialize () {
340 | return this._getter(exports.mclBnFr_serialize)
341 | }
342 | setStr (s, base = 0) {
343 | this._setter(exports.mclBnFr_setStr, s, base)
344 | }
345 | getStr (base = 0) {
346 | return this._getter(exports.mclBnFr_getStr, base)
347 | }
348 | isZero () {
349 | return this._getter(mod._mclBnFr_isZero) === 1
350 | }
351 | isOne () {
352 | return this._getter(mod._mclBnFr_isOne) === 1
353 | }
354 | isEqual (rhs) {
355 | return this._isEqual(mod._mclBnFr_isEqual, rhs)
356 | }
357 | setLittleEndian (s) {
358 | this._setter(exports.mclBnFr_setLittleEndian, s)
359 | }
360 | setLittleEndianMod (s) {
361 | this._setter(exports.mclBnFr_setLittleEndianMod, s)
362 | }
363 | setBigEndianMod (s) {
364 | this._setter(exports.mclBnFr_setBigEndianMod, s)
365 | }
366 | setByCSPRNG () {
367 | const a = new Uint8Array(MCLBN_FR_SIZE)
368 | exports.getRandomValues(a)
369 | this.setLittleEndian(a)
370 | }
371 | setHashOf (s) {
372 | this._setter(exports.mclBnFr_setHashOf, s)
373 | }
374 | }
375 | exports.deserializeHexStrToFr = s => {
376 | const r = new exports.Fr()
377 | r.deserializeHexStr(s)
378 | return r
379 | }
380 |
381 | exports.Id = class extends Common {
382 | constructor () {
383 | super(BLS_ID_SIZE)
384 | }
385 | setInt (x) {
386 | this._setter(mod._blsIdSetInt, x)
387 | }
388 | isEqual (rhs) {
389 | return this._isEqual(mod._blsIdIsEqual, rhs)
390 | }
391 | deserialize (s) {
392 | this._setter(exports.blsIdDeserialize, s)
393 | }
394 | serialize () {
395 | return this._getter(exports.blsIdSerialize)
396 | }
397 | setStr (s, base = 10) {
398 | switch (base) {
399 | case 10:
400 | this._setter(exports.blsIdSetDecStr, s)
401 | return
402 | case 16:
403 | this._setter(exports.blsIdSetHexStr, s)
404 | return
405 | default:
406 | throw ('BlsId.setStr:bad base:' + base)
407 | }
408 | }
409 | getStr (base = 10) {
410 | switch (base) {
411 | case 10:
412 | return this._getter(exports.blsIdGetDecStr)
413 | case 16:
414 | return this._getter(exports.blsIdGetHexStr)
415 | default:
416 | throw ('BlsId.getStr:bad base:' + base)
417 | }
418 | }
419 | setLittleEndian (s) {
420 | this._setter(exports.blsSecretKeySetLittleEndian, s)
421 | }
422 | setLittleEndianMod (s) {
423 | this._setter(exports.blsSecretKeySetLittleEndianMod, s)
424 | }
425 | setByCSPRNG () {
426 | const a = new Uint8Array(BLS_ID_SIZE)
427 | exports.getRandomValues(a)
428 | this.setLittleEndian(a)
429 | }
430 | }
431 | exports.deserializeHexStrToId = s => {
432 | const r = new exports.Id()
433 | r.deserializeHexStr(s)
434 | return r
435 | }
436 |
437 | exports.SecretKey = class extends Common {
438 | constructor () {
439 | super(BLS_SECRETKEY_SIZE)
440 | }
441 | setInt (x) {
442 | this._setter(mod._blsIdSetInt, x) // same as Id
443 | }
444 | isZero () {
445 | return this._getter(mod._blsSecretKeyIsZero) === 1
446 | }
447 | isEqual (rhs) {
448 | return this._isEqual(mod._blsSecretKeyIsEqual, rhs)
449 | }
450 | deserialize (s) {
451 | this._setter(exports.blsSecretKeyDeserialize, s)
452 | }
453 | serialize () {
454 | return this._getter(exports.blsSecretKeySerialize)
455 | }
456 | add (rhs) {
457 | this._update(mod._blsSecretKeyAdd, rhs)
458 | }
459 | share (msk, id) {
460 | callShare(mod._blsSecretKeyShare, this, BLS_SECRETKEY_SIZE, msk, id)
461 | }
462 | recover (secVec, idVec) {
463 | callRecover(mod._blsSecretKeyRecover, this, BLS_SECRETKEY_SIZE, secVec, idVec)
464 | }
465 | setHashOf (s) {
466 | this._setter(exports.blsHashToSecretKey, s)
467 | }
468 | setLittleEndian (s) {
469 | this._setter(exports.blsSecretKeySetLittleEndian, s)
470 | }
471 | setLittleEndianMod (s) {
472 | this._setter(exports.blsSecretKeySetLittleEndianMod, s)
473 | }
474 | setByCSPRNG () {
475 | const a = new Uint8Array(BLS_SECRETKEY_SIZE)
476 | exports.getRandomValues(a)
477 | this.setLittleEndian(a)
478 | }
479 | getPublicKey () {
480 | const pub = new exports.PublicKey()
481 | const secPos = this._allocAndCopy()
482 | const pubPos = pub._alloc()
483 | mod._blsGetPublicKey(pubPos, secPos)
484 | pub._saveAndFree(pubPos)
485 | _free(secPos)
486 | return pub
487 | }
488 | /*
489 | input
490 | m : message (string or Uint8Array)
491 | return
492 | BlsSignature
493 | */
494 | sign (m) {
495 | const sig = new exports.Signature()
496 | const secPos = this._allocAndCopy()
497 | const sigPos = sig._alloc()
498 | exports.blsSign(sigPos, secPos, m)
499 | sig._saveAndFree(sigPos)
500 | _free(secPos)
501 | return sig
502 | }
503 | }
504 | exports.deserializeHexStrToSecretKey = s => {
505 | const r = new exports.SecretKey()
506 | r.deserializeHexStr(s)
507 | return r
508 | }
509 |
510 | exports.PublicKey = class extends Common {
511 | constructor () {
512 | super(BLS_PUBLICKEY_SIZE)
513 | }
514 | isZero () {
515 | return this._getter(mod._blsPublicKeyIsZero) === 1
516 | }
517 | isEqual (rhs) {
518 | return this._isEqual(mod._blsPublicKeyIsEqual, rhs)
519 | }
520 | deserialize (s) {
521 | this._setter(exports.blsPublicKeyDeserialize, s)
522 | }
523 | serialize () {
524 | return this._getter(exports.blsPublicKeySerialize)
525 | }
526 | setStr (s, base = 0) {
527 | const func = ETH_MODE ? exports.mclBnG1_setStr : exports.mclBnG2_setStr
528 | this._setter(func, s, base)
529 | }
530 | getStr (base = 0) {
531 | const func = ETH_MODE ? exports.mclBnG1_getStr : exports.mclBnG2_getStr
532 | return this._getter(func, base)
533 | }
534 | deserializeUncompressed (s) {
535 | this._setter(exports.blsPublicKeyDeserializeUncompressed, s)
536 | }
537 | serializeUncompressed () {
538 | return this._getter(exports.blsPublicKeySerializeUncompressed)
539 | }
540 | add (rhs) {
541 | this._update(mod._blsPublicKeyAdd, rhs)
542 | }
543 | mul (rhs) {
544 | this._update(mod._blsPublicKeyMul, rhs)
545 | }
546 | share (mpk, id) {
547 | callShare(mod._blsPublicKeyShare, this, BLS_PUBLICKEY_SIZE, mpk, id)
548 | }
549 | recover (secVec, idVec) {
550 | callRecover(mod._blsPublicKeyRecover, this, BLS_PUBLICKEY_SIZE, secVec, idVec)
551 | }
552 | isValidOrder () {
553 | return this._getter(mod._blsPublicKeyIsValidOrder)
554 | }
555 | verify (sig, m) {
556 | const pubPos = this._allocAndCopy()
557 | const sigPos = sig._allocAndCopy()
558 | const r = exports.blsVerify(sigPos, pubPos, m)
559 | _free(sigPos)
560 | _free(pubPos)
561 | return r != 0
562 | }
563 | }
564 | exports.deserializeHexStrToPublicKey = s => {
565 | const r = new exports.PublicKey()
566 | r.deserializeHexStr(s)
567 | return r
568 | }
569 | exports.setGeneratorOfPublicKey = pub => {
570 | const pubPos = pub._allocAndCopy()
571 | const r = mod._blsSetGeneratorOfPublicKey(pubPos)
572 | _free(pubPos)
573 | if (r !== 0) throw new Error('bad public key')
574 | }
575 | exports.getGeneratorOfPublicKey = () => {
576 | const pub = new exports.PublicKey()
577 | const pubPos = _malloc(BLS_SIGNATURE_SIZE)
578 | mod._blsGetGeneratorOfPublicKey(pubPos)
579 | pub._saveAndFree(pubPos)
580 | return pub
581 | }
582 | exports.getGeneratorofPublicKey = () => {
583 | console.log('WARNING : getGeneratorofPublicKey is renamed to getGeneratorOfPublicKey')
584 | return exports.getGeneratorOfPublicKey()
585 | }
586 |
587 | exports.Signature = class extends Common {
588 | constructor () {
589 | super(BLS_SIGNATURE_SIZE)
590 | }
591 | isZero () {
592 | return this._getter(mod._blsSignatureIsZero) === 1
593 | }
594 | isEqual (rhs) {
595 | return this._isEqual(mod._blsSignatureIsEqual, rhs)
596 | }
597 | deserialize (s) {
598 | this._setter(exports.blsSignatureDeserialize, s)
599 | }
600 | serialize () {
601 | return this._getter(exports.blsSignatureSerialize)
602 | }
603 | deserializeUncompressed (s) {
604 | this._setter(exports.blsSignatureDeserializeUncompressed, s)
605 | }
606 | setStr (s, base = 0) {
607 | const func = ETH_MODE ? exports.mclBnG2_setStr : exports.mclBnG1_setStr
608 | this._setter(func, s, base)
609 | }
610 | getStr (base = 0) {
611 | const func = ETH_MODE ? exports.mclBnG2_getStr : exports.mclBnG1_getStr
612 | return this._getter(func, base)
613 | }
614 | serializeUncompressed () {
615 | return this._getter(exports.blsSignatureSerializeUncompressed)
616 | }
617 | add (rhs) {
618 | this._update(mod._blsSignatureAdd, rhs)
619 | }
620 | recover (secVec, idVec) {
621 | callRecover(mod._blsSignatureRecover, this, BLS_SIGNATURE_SIZE, secVec, idVec)
622 | }
623 | isValidOrder () {
624 | return this._getter(mod._blsSignatureIsValidOrder)
625 | }
626 | // this = aggSig
627 | aggregate (sigVec) {
628 | const n = sigVec.length
629 | const aggSigPos = this._allocAndCopy()
630 | const sigVecPos = _malloc(BLS_SIGNATURE_SIZE * n)
631 | for (let i = 0; i < n; i++) {
632 | mod.HEAP32.set(sigVec[i].a_, (sigVecPos + BLS_SIGNATURE_SIZE * i) / 4)
633 | }
634 | const r = mod._blsAggregateSignature(aggSigPos, sigVecPos, n)
635 | _free(sigVecPos)
636 | this._saveAndFree(aggSigPos)
637 | return r == 1
638 | }
639 | // this = aggSig
640 | fastAggregateVerify (pubVec, msg) {
641 | const n = pubVec.length
642 | const msgSize = msg.length
643 | const aggSigPos = this._allocAndCopy()
644 | const pubVecPos = _malloc(BLS_PUBLICKEY_SIZE * n)
645 | const msgPos = _malloc(msgSize)
646 | for (let i = 0; i < n; i++) {
647 | mod.HEAP32.set(pubVec[i].a_, (pubVecPos + BLS_PUBLICKEY_SIZE * i) / 4)
648 | }
649 | mod.HEAP8.set(msg, msgPos)
650 | const r = mod._blsFastAggregateVerify(aggSigPos, pubVecPos, n, msgPos, msgSize)
651 | _free(msgPos)
652 | _free(pubVecPos)
653 | _free(aggSigPos)
654 | return r == 1
655 | }
656 | // this = aggSig
657 | // msgVec = (32 * pubVec.length)-size Uint8Array
658 | aggregateVerifyNoCheck (pubVec, msgVec) {
659 | const n = pubVec.length
660 | const msgSize = 32
661 | if (n == 0 || msgVec.length != msgSize * n) {
662 | return false
663 | }
664 | const aggSigPos = this._allocAndCopy()
665 | const pubVecPos = _malloc(BLS_PUBLICKEY_SIZE * n)
666 | const msgPos = _malloc(msgVec.length)
667 | for (let i = 0; i < n; i++) {
668 | mod.HEAP32.set(pubVec[i].a_, (pubVecPos + BLS_PUBLICKEY_SIZE * i) / 4)
669 | }
670 | mod.HEAP8.set(msgVec, msgPos)
671 | const r = mod._blsAggregateVerifyNoCheck(aggSigPos, pubVecPos, msgPos, msgSize, n)
672 | _free(msgPos)
673 | _free(pubVecPos)
674 | _free(aggSigPos)
675 | return r == 1
676 | }
677 | }
678 | exports.deserializeHexStrToSignature = s => {
679 | const r = new exports.Signature()
680 | r.deserializeHexStr(s)
681 | return r
682 | }
683 | // 1 (draft-05) 2 (draft-06) 3 (draft-07)
684 | exports.setETHmode = (mode) => {
685 | if (mod._blsSetETHmode(mode) != 0) throw new Error(`bad setETHmode ${mode}`)
686 | }
687 | exports.setETHserialiation = (enable) => {
688 | mod._mclBn_setETHserialization(enable ? 1 : 0)
689 | }
690 | exports.setMapToMode = (mode) => {
691 | if (mod._mclBn_setMapToMode(mode) != 0) throw new Error(`bad setMapToMode ${mode}`)
692 | }
693 | // make setter check the correctness of the order if doVerify
694 | exports.verifySignatureOrder = (doVerify) => {
695 | mod._blsSignatureVerifyOrder(doVerify)
696 | }
697 | // make setter check the correctness of the order if doVerify
698 | exports.verifyPublicKeyOrder = (doVerify) => {
699 | mod._blsPublicKeyVerifyOrder(doVerify)
700 | }
701 | exports.areAllMsgDifferent = (msgs, msgSize) => {
702 | const n = msgs.length / msgSize
703 | if (msgs.length != n * msgSize) return false
704 | const h = {}
705 | for (let i = 0; i < n; i++) {
706 | const m = msgs.subarray(i * msgSize, (i + 1) * msgSize)
707 | if (m in h) return false
708 | h[m] = true
709 | }
710 | return true
711 | }
712 | /*
713 | return true if all pub[i].verify(sigs[i], msgs[i])
714 | msgs is a concatenation of arrays of 32-byte Uint8Array
715 | */
716 | exports.multiVerify = (pubs, sigs, msgs) => {
717 | const MSG_SIZE = 32
718 | const RAND_SIZE = 8 // 64-bit rand
719 | const threadNum = 0 // not used
720 | const n = sigs.length
721 | if (pubs.length != n || msgs.length != n) return false
722 | for (let i = 0; i < n; i++) {
723 | if (msgs[i].length != MSG_SIZE) return false
724 | }
725 | const sigPos = _malloc(BLS_SIGNATURE_SIZE * n)
726 | const pubPos = _malloc(BLS_PUBLICKEY_SIZE * n)
727 | const msgPos = _malloc(MSG_SIZE * n)
728 | const randPos = _malloc(RAND_SIZE * n)
729 |
730 | // getRandomValues accepts only Uint8Array
731 | const rai = mod.HEAP8.subarray(randPos, randPos + RAND_SIZE * n)
732 | const rau = new Uint8Array(rai.buffer, randPos, rai.length)
733 | exports.getRandomValues(rau)
734 | for (let i = 0; i < n; i++) {
735 | mod.HEAP32.set(sigs[i].a_, (sigPos + BLS_SIGNATURE_SIZE * i) / 4)
736 | mod.HEAP32.set(pubs[i].a_, (pubPos + BLS_PUBLICKEY_SIZE * i) / 4)
737 | mod.HEAP8.set(msgs[i], msgPos + MSG_SIZE * i)
738 | }
739 | const r = mod._blsMultiVerify(sigPos, pubPos, msgPos, MSG_SIZE, randPos, RAND_SIZE, n, threadNum)
740 |
741 | _free(randPos)
742 | _free(msgPos)
743 | _free(pubPos)
744 | _free(sigPos)
745 | return r == 1
746 | }
747 | exports.blsInit(curveType)
748 | if (exports.ethMode) {
749 | exports.setETHmode(exports.ETH_MODE_DRAFT_07)
750 | }
751 | exports.neg = x => {
752 | if (x instanceof exports.Fr) {
753 | return x._op1(mod._mclBnFr_neg)
754 | }
755 | throw new Error('neg:bad type')
756 | }
757 | exports.sqr = x => {
758 | if (x instanceof exports.Fr) {
759 | return x._op1(mod._mclBnFr_sqr)
760 | }
761 | throw new Error('sqr:bad type')
762 | }
763 | exports.inv = x => {
764 | if (x instanceof exports.Fr) {
765 | return x._op1(mod._mclBnFr_inv)
766 | }
767 | throw new Error('inv:bad type')
768 | }
769 | exports.add = (x, y) => {
770 | if (x.constructor !== y.constructor) throw new Error('add:mismatch type')
771 | if (x instanceof exports.Fr) {
772 | return x._op2(mod._mclBnFr_add, y)
773 | }
774 | throw new Error('add:bad type')
775 | }
776 | exports.sub = (x, y) => {
777 | if (x.constructor !== y.constructor) throw new Error('sub:mismatch type')
778 | if (x instanceof exports.Fr) {
779 | return x._op2(mod._mclBnFr_sub, y)
780 | }
781 | throw new Error('sub:bad type')
782 | }
783 | /*
784 | Fr * Fr
785 | */
786 | exports.mul = (x, y) => {
787 | if (x instanceof exports.Fr && y instanceof exports.Fr) {
788 | return x._op2(mod._mclBnFr_mul, y)
789 | }
790 | throw new Error('mul:mismatch type')
791 | }
792 | exports.div = (x, y) => {
793 | if (x.constructor !== y.constructor) throw new Error('div:mismatch type')
794 | if (x instanceof exports.Fr) {
795 | return x._op2(mod._mclBnFr_div, y)
796 | }
797 | throw new Error('div:bad type')
798 | }
799 | exports.hashToFr = s => {
800 | const x = new exports.Fr()
801 | x.setHashOf(s)
802 | return x
803 | }
804 | } // blsSetup()
805 |
806 | const _cryptoGetRandomValues = function(p, n) {
807 | const a = new Uint8Array(n)
808 | exports.getRandomValues(a)
809 | for (let i = 0; i < n; i++) {
810 | exports.mod.HEAP8[p + i] = a[i]
811 | }
812 | }
813 | // f(a:array) fills a with random value
814 | exports.setRandFunc = f => {
815 | exports.getRandomValues = f
816 | }
817 | exports.init = async (curveType = exports.ethMode ? exports.BLS12_381 : exports.BN254) => {
818 | exports.curveType = curveType
819 | exports.getRandomValues = crypto.getRandomValues.bind(crypto)
820 | exports.mod = await createModule({
821 | cryptoGetRandomValues: _cryptoGetRandomValues,
822 | })
823 | blsSetup(exports, curveType)
824 | }
825 | return exports
826 | }
827 |
828 | module.exports = _blsSetupFactory
829 |
--------------------------------------------------------------------------------
/src/index.d.ts:
--------------------------------------------------------------------------------
1 | declare class Common {
2 | constructor(size: number);
3 |
4 | deserializeHexStr(s: string): void;
5 | serializeToHexStr(): string;
6 | dump(msg?: string): void;
7 | clear(): void;
8 | clone(): this;
9 | isEqual(rhs: this): boolean
10 | deserialize(v: Uint8Array): void;
11 | serialize(): Uint8Array;
12 | add(rhs: this): void;
13 | }
14 |
15 | declare class Fr extends Common {
16 | constructor();
17 |
18 | setInt(x: number): void;
19 | deserialize(s: Uint8Array): void;
20 | serialize(): Uint8Array;
21 | setStr(s: string): void;
22 | getStr(): string;
23 | isZero(): boolean;
24 | isOne(): boolean;
25 | isEqual(rhs: this): boolean;
26 | setLittleEndian(a: Uint8Array): void;
27 | setLittleEndianMod(a: Uint8Array): void;
28 | setByCSPRNG(): void;
29 | setHashOf(a: Uint8Array): void;
30 | }
31 |
32 | declare class Id extends Common {
33 | constructor();
34 |
35 | setInt(x: number): void;
36 | isEqual(rhs: this): boolean;
37 | deserialize(s: Uint8Array): void;
38 | serialize(): Uint8Array;
39 | setStr(s: string): void;
40 | getStr(): string;
41 | setLittleEndian(a: Uint8Array): void;
42 | setLittleEndianMod(a: Uint8Array): void;
43 | setByCSPRNG(): void;
44 | }
45 |
46 | declare class SecretKeyType extends Common {
47 | constructor();
48 |
49 | setInt(x: number): void;
50 | isZero(): boolean;
51 | isEqual(rhs: this): boolean;
52 | deserialize(s: Uint8Array): void;
53 | serialize(): Uint8Array;
54 | add(rhs: this): void;
55 | share(msk: SecretKeyType[], id: Id): void;
56 | recover(setVec: any, idVec: any): void;
57 | setHashOf(a: Uint8Array): void;
58 | setLittleEndian(a: Uint8Array): void;
59 | setLittleEndianMod(a: Uint8Array): void;
60 | setByCSPRNG(): void;
61 | getPublicKey(): PublicKeyType;
62 | sign(m: string | Uint8Array): SignatureType;
63 | }
64 |
65 | declare class PublicKeyType extends Common {
66 | constructor();
67 |
68 | isZero(): boolean;
69 | isEqual(rhs: this): boolean;
70 | deserialize(s: Uint8Array): void;
71 | serialize(): Uint8Array;
72 | deserializeUncompressed (s: Uint8Array): void;
73 | serializeUncompressed (): Uint8Array;
74 | add(rhs: this): void;
75 | mul(rhs: SecretKey): void;
76 | share(mpk: PublicKeyType[], id: Id): void;
77 | recover(secVec: PublicKeyType[], idVec: Id[]): void;
78 | isValidOrder(): boolean;
79 | verify(signature: SignatureType, m: Uint8Array | string): boolean;
80 | }
81 |
82 | declare class SignatureType extends Common {
83 | constructor();
84 |
85 | isZero(): boolean;
86 | isEqual(rhs: this): boolean;
87 | deserialize(s: Uint8Array): void;
88 | serialize(): Uint8Array;
89 | deserializeUncompressed (s: Uint8Array): void;
90 | serializeUncompressed (): Uint8Array;
91 | add(rhs: this): void;
92 | recover(secVec: SignatureType[], idVec: Id[]): void;
93 | isValidOrder(): boolean;
94 | aggregate(others: SignatureType[]): boolean;
95 | fastAggregateVerify(publicKeys: PublicKeyType[], message: Uint8Array): boolean;
96 | aggregateVerifyNoCheck(publicKeys: PublicKeyType[], messages: Uint8Array): boolean;
97 | }
98 |
99 | export function init(curveType: CurveType): Promise;
100 | export function blsInit(curveType: CurveType): void;
101 |
102 | export function toHex(a: Uint8Array, start: number, length: number): string;
103 | export function toHexStr(a: Uint8Array): string;
104 | export function fromHexStr(s: string): Uint8Array;
105 | export function deserializeHexStrToSecretKey(s: string): SecretKeyType;
106 | export function deserializeHexStrToPublicKey(s: string): PublicKeyType;
107 | export function deserializeHexStrToSignature(s: string): SignatureType;
108 |
109 | export function getCurveOrder(): string;
110 | export function getFieldOrder(): string;
111 | export function verifySignatureOrder(doVerify: boolean): void;
112 | export function verifyPublicKeyOrder(doVerify: boolean): void;
113 |
114 | /**
115 | *
116 | * @param msgs single array with concatenated messages
117 | * @param msgSize defaults to MSG_SIZE
118 | */
119 | export function areAllMsgDifferent(msgs: Uint8Array, msgSize?: number): boolean;
120 |
121 | /**
122 | * return true if all pub[i].verify(sigs[i], msgs[i])
123 | * @param msgs msgs is a concatenation of arrays of 32-byte Uint8Array
124 | */
125 | export function multiVerify(pubs: PublicKeyType[], sigs: SignatureType[], msgs: Uint8Array[]): boolean;
126 |
127 | export const SecretKey: typeof SecretKeyType;
128 | export const PublicKey: typeof PublicKeyType;
129 | export const Signature: typeof SignatureType;
130 |
131 | export enum CurveType {
132 | BN254 = 0,
133 | BLS12_381 = 5,
134 | }
135 |
136 | export const BN254 = CurveType.BN254;
137 | export const BLS12_381 = CurveType.BLS12_381;
138 | export const ethMode = true;
139 | export const MSG_SIZE = 32;
140 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const createModule = require('./bls_c.js')
2 | const blsSetupFactory = require('./bls')
3 |
4 | const bls = blsSetupFactory(createModule)
5 |
6 | module.exports = bls
7 |
--------------------------------------------------------------------------------
/test/aggregate.txt:
--------------------------------------------------------------------------------
1 | sig 882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb
2 | sig af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe
3 | sig a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6
4 | out ad38fc73846583b08d110d16ab1d026c6ea77ac2071e8ae832f56ac0cbcdeb9f5678ba5ce42bd8dce334cc47b5abcba40a58f7f1f80ab304193eb98836cc14d8183ec14cc77de0f80c4ffd49e168927a968b5cdaa4cf46b9805be84ad7efa77b
5 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55
6 | sig b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9
7 | sig 948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115
8 | out 9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31
9 | sig 91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121
10 | sig 9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df
11 | sig ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9
12 | out 9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930
13 |
--------------------------------------------------------------------------------
/test/aggregate_verify.txt:
--------------------------------------------------------------------------------
1 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
2 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
3 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
4 | msg 0000000000000000000000000000000000000000000000000000000000000000
5 | msg 5656565656565656565656565656565656565656565656565656565656565656
6 | msg abababababababababababababababababababababababababababababababab
7 | sig 9104e74bffffffff
8 | out false
9 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
10 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
11 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
12 | msg 0000000000000000000000000000000000000000000000000000000000000000
13 | msg 5656565656565656565656565656565656565656565656565656565656565656
14 | msg abababababababababababababababababababababababababababababababab
15 | sig 9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244
16 | out true
17 |
--------------------------------------------------------------------------------
/test/bench.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const bls = require('../src/index.js')
3 | const assert = require('assert')
4 | const { performance } = require('perf_hooks')
5 |
6 | const curveTest = (curveType, name) => {
7 | bls.init(curveType)
8 | .then(() => {
9 | try {
10 | console.log(`name=${name} curve order=${bls.getCurveOrder()}`)
11 | benchAll()
12 | } catch (e) {
13 | console.log('TEST FAIL', e)
14 | assert(false)
15 | }
16 | })
17 | }
18 |
19 | async function curveTestAll () {
20 | // can't parallel
21 | await curveTest(bls.BLS12_381, 'BLS12_381')
22 | }
23 |
24 | curveTestAll()
25 |
26 | function bench (label, count, func) {
27 | const start = performance.now()
28 | for (let i = 0; i < count; i++) {
29 | func()
30 | }
31 | const end = performance.now()
32 | const t = (end - start) / count
33 | const roundTime = (Math.round(t * 1000)) / 1000
34 | console.log(label + ' ' + roundTime)
35 | }
36 |
37 | function benchBls () {
38 | const msg = 'hello wasm'
39 | const sec = new bls.SecretKey()
40 | sec.setByCSPRNG()
41 | const pub = sec.getPublicKey()
42 | bench('time_sign_class', 1000, () => sec.sign(msg))
43 | const sig = sec.sign(msg)
44 | bench('time_verify_class', 300, () => pub.verify(sig, msg))
45 | }
46 |
47 | function benchAll () {
48 | benchBls()
49 | }
50 |
--------------------------------------------------------------------------------
/test/fast_aggregate_verify.txt:
--------------------------------------------------------------------------------
1 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
2 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
3 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
4 | msg abababababababababababababababababababababababababababababababab
5 | sig 9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfcffffffff
6 | out false
7 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
8 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
9 | msg 5656565656565656565656565656565656565656565656565656565656565656
10 | sig 912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f7797ffffffff
11 | out false
12 | msg abababababababababababababababababababababababababababababababab
13 | sig c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
14 | out false
15 | msg abababababababababababababababababababababababababababababababab
16 | sig 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
17 | out false
18 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
19 | msg 0000000000000000000000000000000000000000000000000000000000000000
20 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55
21 | out true
22 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
23 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
24 | msg 5656565656565656565656565656565656565656565656565656565656565656
25 | sig 912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f779746d830d1
26 | out true
27 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
28 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
29 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
30 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
31 | msg abababababababababababababababababababababababababababababababab
32 | sig 9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930
33 | out false
34 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
35 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
36 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
37 | msg abababababababababababababababababababababababababababababababab
38 | sig 9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930
39 | out true
40 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
41 | msg 0000000000000000000000000000000000000000000000000000000000000000
42 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380bffffffff
43 | out false
44 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
45 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
46 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
47 | msg 5656565656565656565656565656565656565656565656565656565656565656
48 | sig 912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f779746d830d1
49 | out false
50 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
51 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
52 | msg 0000000000000000000000000000000000000000000000000000000000000000
53 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55
54 | out false
55 |
--------------------------------------------------------------------------------
/test/mcl-test.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const bls = require('../src/index.js')
3 | const assert = require('assert')
4 |
5 | const curveTest = (curveType, name) => {
6 | bls.init(curveType)
7 | .then(() => {
8 | try {
9 | console.log(`name=${name}`)
10 | FrTest()
11 | } catch (e) {
12 | console.log(`TEST FAIL ${e}`)
13 | assert(false)
14 | }
15 | })
16 | }
17 |
18 | async function curveTestAll () {
19 | await curveTest(bls.BLS12_381, 'BLS12_381')
20 | }
21 |
22 | curveTestAll()
23 |
24 | function FrTest () {
25 | const a = new bls.Fr()
26 | a.setInt(5)
27 | assert.equal(a.getStr(), '5')
28 | a.setStr('65535')
29 | assert.equal(a.getStr(), '65535')
30 | assert.equal(a.getStr(16), 'ffff')
31 | a.setStr('ff', 16)
32 | assert.equal(a.getStr(), '255')
33 | a.setStr('0x10')
34 | assert.equal(a.getStr(), '16')
35 | assert.equal(a.getStr(16), '10')
36 | const b = new bls.Fr()
37 | a.setByCSPRNG()
38 | b.deserialize(a.serialize())
39 | assert.deepEqual(a.serialize(), b.serialize())
40 | a.setStr('1000000000020')
41 | b.setInt(-15)
42 | assert.equal(bls.add(a, b).getStr(), '1000000000005')
43 | assert.equal(bls.sub(a, b).getStr(), '1000000000035')
44 | a.setInt(200)
45 | b.setInt(20)
46 | assert.equal(bls.mul(a, b).getStr(), '4000')
47 | assert.equal(bls.div(a, b).getStr(), '10')
48 | assert.equal(bls.mul(bls.div(b, a), a).getStr(), '20')
49 | a.setInt(-123)
50 | assert.equal(bls.neg(a).getStr(), '123')
51 | assert.equal(bls.mul(a, bls.inv(a)).getStr(), '1')
52 | a.setInt(123459)
53 | assert(bls.mul(a, a).isEqual(bls.sqr(a)))
54 |
55 | a.setInt(3)
56 | assert(!a.isZero())
57 | assert(!a.isOne())
58 | a.setInt(1)
59 | assert(!a.isZero())
60 | assert(a.isOne())
61 | a.setInt(0)
62 | assert(a.isZero())
63 | assert(!a.isOne())
64 | a.setInt(5)
65 | b.setInt(3)
66 | assert(!a.isEqual(b))
67 | b.setInt(5)
68 | assert(a.isEqual(b))
69 |
70 | a.setHashOf('abc')
71 | a.dump()
72 | b.setHashOf([97, 98, 99])
73 | assert(a.isEqual(b))
74 |
75 | b.clear()
76 | b.deserialize(a.serialize())
77 | assert(a.isEqual(b))
78 | a.setLittleEndianMod(new Uint8Array([1, 2, 3]))
79 | b.setInt(1 + 256 * (2 + 256 * 3))
80 | assert(a.isEqual(b))
81 | a.clear()
82 | a.setLittleEndian(new Uint8Array([1, 2, 3]))
83 | assert(a.isEqual(b))
84 | a.clear()
85 | a.setBigEndianMod(new Uint8Array([3, 2, 1]))
86 | assert(a.isEqual(b))
87 | a.setByCSPRNG()
88 | console.log(`rand ${a.getStr(16)}`)
89 | }
90 |
--------------------------------------------------------------------------------
/test/sign.txt:
--------------------------------------------------------------------------------
1 | sec 328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216
2 | msg abababababababababababababababababababababababababababababababab
3 | out ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9
4 | sec 47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138
5 | msg abababababababababababababababababababababababababababababababab
6 | out 9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df
7 | sec 328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216
8 | msg 5656565656565656565656565656565656565656565656565656565656565656
9 | out a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6
10 | sec 47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138
11 | msg 5656565656565656565656565656565656565656565656565656565656565656
12 | out af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe
13 | sec 263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3
14 | msg 0000000000000000000000000000000000000000000000000000000000000000
15 | out b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55
16 | sec 47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138
17 | msg 0000000000000000000000000000000000000000000000000000000000000000
18 | out b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9
19 | sec 328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216
20 | msg 0000000000000000000000000000000000000000000000000000000000000000
21 | out 948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115
22 | sec 263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3
23 | msg abababababababababababababababababababababababababababababababab
24 | out 91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121
25 | sec 263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3
26 | msg 5656565656565656565656565656565656565656565656565656565656565656
27 | out 882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb
28 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const bls = require('../src/index.js')
3 | const assert = require('assert')
4 | const fs = require('fs')
5 | const readline = require('readline')
6 | const { performance } = require('perf_hooks')
7 |
8 | const curveTest = (curveType, name) => {
9 | bls.init(curveType)
10 | .then(() => {
11 | try {
12 | console.log(`name=${name} curve order=${bls.getCurveOrder()}`)
13 | serializeTest()
14 | zeroTest()
15 | signatureTest()
16 | opTest()
17 | miscTest()
18 | shareTest()
19 | addTest()
20 | ethTest()
21 | console.log('all ok')
22 | benchAll()
23 | } catch (e) {
24 | console.log('TEST FAIL', e)
25 | assert(false)
26 | }
27 | })
28 | }
29 |
30 | async function curveTestAll () {
31 | // can't parallel
32 | await curveTest(bls.BLS12_381, 'BLS12_381')
33 | }
34 |
35 | curveTestAll()
36 |
37 | function serializeSubTest (t, Cstr) {
38 | const s = t.serializeToHexStr()
39 | const t2 = new Cstr()
40 | t2.deserializeHexStr(s)
41 | assert.deepEqual(t.serialize(), t2.serialize())
42 | }
43 |
44 | function serializeUncompressedSubTest (t, Cstr) {
45 | const b = t.serializeUncompressed()
46 | const t2 = new Cstr()
47 | t2.deserializeUncompressed(b)
48 | assert(t.isEqual(t2))
49 | }
50 |
51 | function serializeTest () {
52 | const sec = new bls.SecretKey()
53 | sec.setByCSPRNG()
54 | serializeSubTest(sec, bls.SecretKey)
55 | const pub = sec.getPublicKey()
56 | serializeSubTest(pub, bls.PublicKey)
57 | serializeUncompressedSubTest(pub, bls.PublicKey)
58 | const msg = 'abc'
59 | const sig = sec.sign(msg)
60 | serializeSubTest(sig, bls.Signature)
61 | serializeUncompressedSubTest(sig, bls.Signature)
62 | const id = new bls.Id()
63 | id.setStr('12345')
64 | serializeSubTest(id, bls.Id)
65 | }
66 |
67 | function zeroTest () {
68 | let sec = new bls.SecretKey()
69 | assert(sec.isZero())
70 | sec.setByCSPRNG()
71 | assert(!sec.isZero())
72 | let pub = new bls.PublicKey()
73 | assert(pub.isZero())
74 | pub = sec.getPublicKey()
75 | assert(!pub.isZero())
76 | let sig = new bls.Signature()
77 | assert(sig.isZero())
78 | sig = sec.sign('abc')
79 | assert(!sig.isZero())
80 | }
81 |
82 | function signatureTest () {
83 | const sec = new bls.SecretKey()
84 |
85 | sec.setByCSPRNG()
86 | sec.dump('secretKey ')
87 |
88 | const pub = sec.getPublicKey()
89 | pub.dump('publicKey ')
90 |
91 | const msg = 'doremifa'
92 | console.log('msg ' + msg)
93 | const sig = sec.sign(msg)
94 | sig.dump('signature ')
95 |
96 | assert(pub.verify(sig, msg))
97 | }
98 |
99 | function opTest () {
100 | console.log('opTest')
101 | const sec1 = new bls.SecretKey()
102 | const sec2 = new bls.SecretKey()
103 | sec1.setByCSPRNG()
104 | sec2.setByCSPRNG()
105 | const pub1 = sec1.getPublicKey()
106 | const pub2 = sec2.getPublicKey()
107 | sec1.dump('sec1 ')
108 | sec2.dump('sec2 ')
109 | pub1.dump('pub1 ')
110 | pub2.dump('pub2 ')
111 |
112 | const msg = 'doremifa'
113 | const sig1 = sec1.sign(msg)
114 | const sig2 = sec2.sign(msg)
115 | assert(pub1.verify(sig1, msg))
116 | assert(pub2.verify(sig2, msg))
117 | // add
118 | {
119 | const sec = sec1.clone()
120 | sec.add(sec2)
121 | sec.dump('sec ')
122 | const pub = pub1.clone()
123 | pub.add(pub2)
124 | pub.dump('pub ')
125 | const sig = sig1.clone()
126 | sig.add(sig2)
127 | sig.dump('sig ')
128 | assert(pub.verify(sig, msg))
129 | }
130 | // mul
131 | pub1.mul(sec2)
132 | pub1.dump('pub1*sec2 ')
133 | pub2.mul(sec1)
134 | pub2.dump('pub2*sec1 ')
135 | assert(pub1.isEqual(pub2))
136 | }
137 |
138 | function bench (label, count, func) {
139 | const start = performance.now()
140 | for (let i = 0; i < count; i++) {
141 | func()
142 | }
143 | const end = performance.now()
144 | const t = (end - start) / count
145 | const roundTime = (Math.round(t * 1000)) / 1000
146 | console.log(label + ' ' + roundTime)
147 | }
148 |
149 | function benchBls () {
150 | const msg = 'hello wasm'
151 | const sec = new bls.SecretKey()
152 | sec.setByCSPRNG()
153 | const pub = sec.getPublicKey()
154 | bench('time_sign_class', 50, () => sec.sign(msg))
155 | const sig = sec.sign(msg)
156 | bench('time_verify_class', 50, () => pub.verify(sig, msg))
157 | }
158 |
159 | function benchAll () {
160 | benchBls()
161 | }
162 |
163 | /*
164 | return [min, max)
165 | assume min < max
166 | */
167 | function randRange (min, max) {
168 | return min + Math.floor(Math.random() * (max - min))
169 | }
170 |
171 | /*
172 | select k of [0, n)
173 | @note not uniformal distribution
174 | */
175 | function randSelect (k, n) {
176 | let a = []
177 | let prev = -1
178 | for (let i = 0; i < k; i++) {
179 | const v = randRange(prev + 1, n - (k - i) + 1)
180 | a.push(v)
181 | prev = v
182 | }
183 | return a
184 | }
185 |
186 | function miscTest () {
187 | const idDec = '65535'
188 | const id = new bls.Id()
189 | id.setStr(idDec)
190 | assert(id.getStr(), '65535')
191 | assert(id.getStr(16), 'ffff')
192 | }
193 |
194 | function shareTest () {
195 | const k = 4
196 | const n = 10
197 | const msg = 'this is a pen'
198 | const msk = []
199 | const mpk = []
200 | const idVec = []
201 | const secVec = []
202 | const pubVec = []
203 | const sigVec = []
204 |
205 | /*
206 | setup master secret key
207 | */
208 | for (let i = 0; i < k; i++) {
209 | const sk = new bls.SecretKey()
210 | sk.setByCSPRNG()
211 | msk.push(sk)
212 |
213 | const pk = sk.getPublicKey()
214 | mpk.push(pk)
215 | }
216 | const secStr = msk[0].serializeToHexStr()
217 | const pubStr = mpk[0].serializeToHexStr()
218 | const sigStr = msk[0].sign(msg).serializeToHexStr()
219 | assert(mpk[0].verify(msk[0].sign(msg), msg))
220 |
221 | /*
222 | key sharing
223 | */
224 | for (let i = 0; i < n; i++) {
225 | const id = new bls.Id()
226 | // blsIdSetInt(id, i + 1)
227 | id.setByCSPRNG()
228 | idVec.push(id)
229 | const sk = new bls.SecretKey()
230 | sk.share(msk, idVec[i])
231 | secVec.push(sk)
232 |
233 | const pk = new bls.PublicKey()
234 | pk.share(mpk, idVec[i])
235 | pubVec.push(pk)
236 |
237 | const sig = sk.sign(msg)
238 | sigVec.push(sig)
239 | }
240 |
241 | /*
242 | recover
243 | */
244 | const idxVec = randSelect(k, n)
245 | console.log('idxVec=' + idxVec)
246 | let subIdVec = []
247 | let subSecVec = []
248 | let subPubVec = []
249 | let subSigVec = []
250 | for (let i = 0; i < idxVec.length; i++) {
251 | let idx = idxVec[i]
252 | subIdVec.push(idVec[idx])
253 | subSecVec.push(secVec[idx])
254 | subPubVec.push(pubVec[idx])
255 | subSigVec.push(sigVec[idx])
256 | }
257 | {
258 | const sec = new bls.SecretKey()
259 | const pub = new bls.PublicKey()
260 | const sig = new bls.Signature()
261 |
262 | sec.recover(subSecVec, subIdVec)
263 | pub.recover(subPubVec, subIdVec)
264 | sig.recover(subSigVec, subIdVec)
265 | assert(sec.serializeToHexStr(), secStr)
266 | assert(pub.serializeToHexStr(), pubStr)
267 | assert(sig.serializeToHexStr(), sigStr)
268 | }
269 | }
270 |
271 | function addTest () {
272 | const n = 5
273 | const m = 'abc'
274 | const sec = []
275 | const pub = []
276 | const sig = []
277 | for (let i = 0; i < n; i++) {
278 | sec.push(new bls.SecretKey())
279 | sec[i].setByCSPRNG()
280 | pub.push(sec[i].getPublicKey())
281 | sig.push(sec[i].sign(m))
282 | assert(pub[i].verify(sig[i], m))
283 | }
284 | for (let i = 1; i < n; i++) {
285 | sec[0].add(sec[i])
286 | pub[0].add(pub[i])
287 | sig[0].add(sig[i])
288 | }
289 | assert(pub[0].verify(sig[0], m))
290 | const sig2 = sec[0].sign(m)
291 | assert(sig2.isEqual(sig[0]))
292 | }
293 |
294 | function ethAggregateTest () {
295 | const fileName = 'test/aggregate.txt'
296 | console.log(`fileName=${fileName}`)
297 | const rs = fs.createReadStream(fileName)
298 | const rl = readline.createInterface({input: rs})
299 | let sigVec = []
300 | rl.on('line', (line) => {
301 | const [k, v] = line.split(' ')
302 | if (k === 'sig') {
303 | sigVec.push(verifyDeserializeSignature(v))
304 | } else if (k === 'out') {
305 | const out = verifyDeserializeSignature(v)
306 | const agg = new bls.Signature()
307 | agg.aggregate(sigVec)
308 | assert(agg.isEqual(out))
309 | sigVec = []
310 | }
311 | })
312 | }
313 |
314 | function ethSignOneTest (secHex, msgHex, sigHex) {
315 | console.log(`sec=${secHex}`)
316 | const sec = bls.deserializeHexStrToSecretKey(secHex)
317 | const pub = sec.getPublicKey()
318 | const msg = bls.fromHexStr(msgHex)
319 | const sig = sec.sign(msg)
320 | assert(pub.verify(sig, msg))
321 | const s = sig.serializeToHexStr()
322 | assert(s === sigHex)
323 | }
324 |
325 | function ethSignTest () {
326 | let secHex = ''
327 | let msgHex = ''
328 | const fileName = 'test/sign.txt'
329 | console.log(`fileName=${fileName}`)
330 | const rs = fs.createReadStream(fileName)
331 | const rl = readline.createInterface({input: rs})
332 | rl.on('line', (line) => {
333 | const [k, v] = line.split(' ')
334 | if (k === 'sec') {
335 | secHex = v
336 | } else if (k === 'msg') {
337 | msgHex = v
338 | } else if (k === 'out') {
339 | ethSignOneTest(secHex, msgHex, v)
340 | } else {
341 | assert(false)
342 | }
343 | })
344 | }
345 |
346 | function ethAggregateVerifyNoCheckTest () {
347 | const fileName = 'test/aggregate_verify.txt'
348 | console.log(`fileName=${fileName}`)
349 | const rs = fs.createReadStream(fileName)
350 | const rl = readline.createInterface({input: rs})
351 |
352 | let pubVec = []
353 | let msgHex = ''
354 | let sig = null
355 | rl.on('line', (line) => {
356 | const [k, v] = line.split(' ')
357 | if (k === 'pub') {
358 | pubVec.push(bls.deserializeHexStrToPublicKey(v))
359 | } else if (k === 'msg') {
360 | msgHex += v
361 | } else if (k === 'sig') {
362 | sig = verifyDeserializeSignature(v)
363 | } else if (k === 'out') {
364 | const out = v === 'true'
365 | const msgVec = bls.fromHexStr(msgHex)
366 | const r = sig.aggregateVerifyNoCheck(pubVec, msgVec)
367 | assert(r === out)
368 | pubVec = []
369 | msgHex = ''
370 | }
371 | })
372 | }
373 |
374 | function verifyDeserializeSignature (sigHex) {
375 | try {
376 | return bls.deserializeHexStrToSignature(sigHex)
377 | } catch (e) {
378 | console.log(`bad sig ${sigHex}`)
379 | return new bls.Signature()
380 | }
381 | }
382 |
383 | function ethFastAggregateVerifyTest () {
384 | const fileName = 'test/fast_aggregate_verify.txt'
385 | const rs = fs.createReadStream(fileName)
386 | const rl = readline.createInterface({input: rs})
387 |
388 | let pubVec = []
389 | let msg = ''
390 | let sig = null
391 | rl.on('line', (line) => {
392 | const [k, v] = line.split(' ')
393 | if (k === 'pub') {
394 | pubVec.push(bls.deserializeHexStrToPublicKey(v))
395 | } else if (k === 'msg') {
396 | msg = bls.fromHexStr(v)
397 | } else if (k === 'sig') {
398 | sig = verifyDeserializeSignature(v)
399 | } else if (k === 'out') {
400 | const out = v === 'true'
401 | if (!sig.isValidOrder()) {
402 | console.log('bad order')
403 | pubVec = []
404 | return
405 | }
406 | const r = sig.fastAggregateVerify(pubVec, msg)
407 | assert(r === out)
408 | pubVec = []
409 | }
410 | })
411 | }
412 |
413 | function blsAggregateVerifyNoCheckTestOne (n) {
414 | console.log(`blsAggregateVerifyNoCheckTestOne ${n}`)
415 | const msgSize = 32
416 | const pubs = []
417 | const sigs = []
418 | const msgs = new Uint8Array(msgSize * n)
419 | for (let i = 0; i < n; i++) {
420 | var sec = new bls.SecretKey()
421 | sec.setByCSPRNG()
422 | pubs.push(sec.getPublicKey())
423 | msgs[msgSize * i] = i
424 | sigs.push(sec.sign(msgs.subarray(i * msgSize, (i + 1) * msgSize)))
425 | assert(pubs[i].isValidOrder())
426 | assert(sigs[i].isValidOrder())
427 | }
428 | assert(bls.areAllMsgDifferent(msgs, msgSize))
429 | const aggSig = new bls.Signature()
430 | aggSig.aggregate(sigs)
431 | assert(aggSig.aggregateVerifyNoCheck(pubs, msgs))
432 | msgs[1] = 1
433 | assert(!aggSig.aggregateVerifyNoCheck(pubs, msgs))
434 | }
435 |
436 | function blsAggregateVerifyNoCheckTest () {
437 | const tbl = [1, 2, 15, 16, 17, 50]
438 | tbl.forEach((n) => {
439 | blsAggregateVerifyNoCheckTestOne(n)
440 | })
441 | }
442 |
443 | function multiVerifyTestOne (n) {
444 | const msgSize = 32
445 | const pubs = []
446 | const sigs = []
447 | const msgs = []
448 | const sec = new bls.SecretKey()
449 | for (let i = 0; i < n; i++) {
450 | sec.setByCSPRNG()
451 | pubs.push(sec.getPublicKey())
452 | const msg = new Uint8Array(msgSize)
453 | bls.getRandomValues(msg)
454 | msgs.push(msg)
455 | sigs.push(sec.sign(msg))
456 | }
457 | assert(bls.multiVerify(pubs, sigs, msgs))
458 | if (n === 50) {
459 | bench('multiVerify', 10, () => bls.multiVerify(pubs, sigs, msgs))
460 | bench('normal verify', 10, () => {
461 | for (let i = 0; i < n; i++) {
462 | pubs[i].verify(sigs[i], msgs[i])
463 | }
464 | })
465 | }
466 | msgs[0][0]++
467 | assert(!bls.multiVerify(pubs, sigs, msgs))
468 | }
469 |
470 | function multiVerifyTest () {
471 | const tbl = [1, 2, 15, 16, 17, 30, 31, 32, 33, 50, 400]
472 | tbl.forEach((n) => {
473 | console.log(`multiVerifyTestOne ${n}`)
474 | multiVerifyTestOne(n)
475 | })
476 | }
477 |
478 | function blsDraft07 () {
479 | const secHex = '0000000000000000000000000000000000000000000000000000000000000001'
480 | const msgHex = '61736466'
481 | const sigHex = 'b45a264e0d6f8614c4640ea97bae13effd3c74c4e200e3b1596d6830debc952602a7d210eca122dc4f596fa01d7f6299106933abd29477606f64588595e18349afe22ecf2aeeeb63753e88a42ef85b24140847e05620a28422f8c30f1d33b9aa'
482 | ethSignOneTest(secHex, msgHex, sigHex)
483 | }
484 |
485 | function ethVerifyOneTest (pubHex, msgHex, sigHex, outStr) {
486 | const pub = bls.deserializeHexStrToPublicKey(pubHex)
487 | const msg = bls.fromHexStr(msgHex)
488 | const expect = outStr === 'true'
489 | const sig = verifyDeserializeSignature(sigHex)
490 | const b = pub.verify(sig, msg)
491 | assert(b === expect)
492 | }
493 |
494 | function ethVerifyTest () {
495 | const fileName = 'test/verify.txt'
496 | console.log(`fileName=${fileName}`)
497 | const rs = fs.createReadStream(fileName)
498 | const rl = readline.createInterface({input: rs})
499 | let pubHex = ''
500 | let msgHex = ''
501 | let sigHex = ''
502 | let outStr = ''
503 | rl.on('line', (line) => {
504 | const [k, v] = line.split(' ')
505 | if (k === 'pub') {
506 | pubHex = v
507 | } else if (k === 'msg') {
508 | msgHex = v
509 | } else if (k === 'sig') {
510 | sigHex = v
511 | } else if (k === 'out') {
512 | outStr = v
513 | ethVerifyOneTest(pubHex, msgHex, sigHex, outStr)
514 | }
515 | })
516 | }
517 |
518 | function ethTest () {
519 | blsDraft07()
520 | ethAggregateTest()
521 | ethSignTest()
522 | ethVerifyTest()
523 | ethAggregateVerifyNoCheckTest()
524 | ethFastAggregateVerifyTest()
525 | blsAggregateVerifyNoCheckTest()
526 | multiVerifyTest()
527 | }
528 |
--------------------------------------------------------------------------------
/test/verify.txt:
--------------------------------------------------------------------------------
1 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
2 | msg abababababababababababababababababababababababababababababababab
3 | sig 9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df
4 | out true
5 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
6 | msg abababababababababababababababababababababababababababababababab
7 | sig 91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b71ffffffff
8 | out false
9 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
10 | msg 0000000000000000000000000000000000000000000000000000000000000000
11 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55
12 | out false
13 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
14 | msg 5656565656565656565656565656565656565656565656565656565656565656
15 | sig a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6
16 | out false
17 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
18 | msg abababababababababababababababababababababababababababababababab
19 | sig 91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121
20 | out true
21 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
22 | msg 5656565656565656565656565656565656565656565656565656565656565656
23 | sig af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363ffffffff
24 | out false
25 | pub c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
26 | msg abababababababababababababababababababababababababababababababab
27 | sig c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
28 | out false
29 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
30 | msg 5656565656565656565656565656565656565656565656565656565656565656
31 | sig af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe
32 | out false
33 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
34 | msg abababababababababababababababababababababababababababababababab
35 | sig ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9
36 | out true
37 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
38 | msg 5656565656565656565656565656565656565656565656565656565656565656
39 | sig a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffffffff
40 | out false
41 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
42 | msg abababababababababababababababababababababababababababababababab
43 | sig 91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121
44 | out false
45 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
46 | msg abababababababababababababababababababababababababababababababab
47 | sig ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9ffffffff
48 | out false
49 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
50 | msg 0000000000000000000000000000000000000000000000000000000000000000
51 | sig 948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115
52 | out false
53 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
54 | msg 0000000000000000000000000000000000000000000000000000000000000000
55 | sig b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9
56 | out false
57 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
58 | msg 0000000000000000000000000000000000000000000000000000000000000000
59 | sig b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dffffffff
60 | out false
61 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
62 | msg 0000000000000000000000000000000000000000000000000000000000000000
63 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380bffffffff
64 | out false
65 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
66 | msg 5656565656565656565656565656565656565656565656565656565656565656
67 | sig 882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972ffffffff
68 | out false
69 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
70 | msg abababababababababababababababababababababababababababababababab
71 | sig 9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5ffffffff
72 | out false
73 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
74 | msg abababababababababababababababababababababababababababababababab
75 | sig ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9
76 | out false
77 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
78 | msg 0000000000000000000000000000000000000000000000000000000000000000
79 | sig 948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075effffffff
80 | out false
81 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
82 | msg abababababababababababababababababababababababababababababababab
83 | sig 9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df
84 | out false
85 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
86 | msg 5656565656565656565656565656565656565656565656565656565656565656
87 | sig 882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb
88 | out true
89 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
90 | msg 0000000000000000000000000000000000000000000000000000000000000000
91 | sig 948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115
92 | out true
93 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
94 | msg 5656565656565656565656565656565656565656565656565656565656565656
95 | sig 882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb
96 | out false
97 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
98 | msg 0000000000000000000000000000000000000000000000000000000000000000
99 | sig b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9
100 | out true
101 | pub b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81
102 | msg 5656565656565656565656565656565656565656565656565656565656565656
103 | sig af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe
104 | out true
105 | pub a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a
106 | msg 0000000000000000000000000000000000000000000000000000000000000000
107 | sig b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55
108 | out true
109 | pub b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f
110 | msg 5656565656565656565656565656565656565656565656565656565656565656
111 | sig a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6
112 | out true
113 |
--------------------------------------------------------------------------------