├── .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 | [![Build Status](https://github.com/herumi/bls-eth-wasm/actions/workflows/main.yml/badge.svg)](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 | --------------------------------------------------------------------------------