diff --git a/circuits/cpp/barretenberg/ts/bin-test/Nargo.toml b/circuits/cpp/barretenberg/ts/bin-test/Nargo.toml index 670888e37cd6..d2890cc5e86b 100644 --- a/circuits/cpp/barretenberg/ts/bin-test/Nargo.toml +++ b/circuits/cpp/barretenberg/ts/bin-test/Nargo.toml @@ -1,5 +1,7 @@ [package] +name = "main" +type = "bin" authors = [""] -compiler_version = "0.6.0" +compiler_version = "0.10.1" [dependencies] \ No newline at end of file diff --git a/circuits/cpp/barretenberg/ts/bin-test/bin-test.sh b/circuits/cpp/barretenberg/ts/bin-test/bin-test.sh index 49c0ee1bda55..1639c4c03bcb 100755 --- a/circuits/cpp/barretenberg/ts/bin-test/bin-test.sh +++ b/circuits/cpp/barretenberg/ts/bin-test/bin-test.sh @@ -1,11 +1,5 @@ #!/bin/sh -set -eu -bb() { - ../dest/node/main.js -v "$@" -} +echo "NodeJS version: $(node --version)" -bb gates -bb prove -o proof -bb write_vk -o vk -bb verify -k vk -p proof \ No newline at end of file +node ./test.js diff --git a/circuits/cpp/barretenberg/ts/bin-test/src/main.nr b/circuits/cpp/barretenberg/ts/bin-test/src/main.nr index 7c5b52896610..571749b8e9b9 100644 --- a/circuits/cpp/barretenberg/ts/bin-test/src/main.nr +++ b/circuits/cpp/barretenberg/ts/bin-test/src/main.nr @@ -8,18 +8,19 @@ fn main( input_aggregation_object : [Field; 16], proof_b : [Field; 94], ) -> pub [Field; 16] { + let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), key_hash, input_aggregation_object ); let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), key_hash, output_aggregation_object_a ); diff --git a/circuits/cpp/barretenberg/ts/bin-test/target/main.bytecode b/circuits/cpp/barretenberg/ts/bin-test/target/main.bytecode index fee406537ed1..59139a8792a7 100644 --- a/circuits/cpp/barretenberg/ts/bin-test/target/main.bytecode +++ b/circuits/cpp/barretenberg/ts/bin-test/target/main.bytecode @@ -1 +1 @@ -H4sIAAAAAAAA/+3YY4xkaRhA4e6xp8e2bavHtj2ztjG2bdu2bWttjm3P9uyp9OnNZP/uJrOb9E2enNxblU5V3qrvVn8dg4OCYgaFH9HtB5aHgqIgKqL5eIyg8OfHQmzEQVzEQ3wkQEKEIBESIwmSIhmSIwVSIhVSIw3SIh3SIwMyIhMyIwuyIhuyIwdyIhdyIw/yIh/yowAKohAKowiKohiKowRKohRKowzKohzKowJCURGVUBlVUBXVUB01UBO1UBt1UBf1UB8N0BCN0BhN0BTN0Bwt0BKt0Bpt0Bbt0B4d0BEv4EW8hJfxCl7Fa3gdb+BNvIW38Q7exXt431lGd5btnOuH+Agf4xN8ik7ojC7oim7ojh7oiV7ojT7oi37ojwEYiEEYjCEYimEYjhEYiVEYjTEYi3EYjwmYiEmYjCmYimmYjhmYiVmYjTmYi3mYjwVYiEVYjCVYimVYjhVYiVVYjTVYi3VYjw3YiE3YjC3Yim3Yjh3YiV3YjT3Yi33YjwM4iEM4jCM4imM4jhM4iVPOIYqzCByfeS3w/Qrx2hf4El/ha3yDb/EdvscP+BE/4Wf8gl/xG3737wW+qxGzPo0zOItzOI8LuIhLuIwruIpruI4buIlbuI07uIt7uI8HeIhHeIwn+ANheBoU/gaDEQVREQ3RESOw1iAWYiMO4iIe4iMBEiIEiZAYSZAUyZAcKZASqZAaaZAW6ZAeGZARmZAZWZAV2ZAdOZATuZAbeZAX+ZAfBVAQhVAYRVAUxVAcJVASpVAaZVAW5VAeFRAaHD7jwHr47Foa5vzDnHmYswpzboHGsDFtLBvbxrFxbTwb3yawCW2ITWQT2yQ2qU1mk9sUNqVNZVPbNDatTWfT2ww2o81kM9ssNqvNZrPbHDanzWVz2zw2r81n89sCtqAtZAvbIraoLWaL2xK2pC1lS9sytqwtZ8vbCjbUVrSVbGVbxVa11Wx1W8PWtLVsbVvH1rX1bH3bwDa0jWxj28Q2tc1sc9vCtrStbGvbxra17Wx728F2tC/YF+1L9mX7in3VvmZft2/YN+1b9m37jn3Xvmfftx888zoDx4eef2Q/tp/YT20n29l2sV1tN9vd9rA9bS/b2/axfW0/298OsAPtIDvYDrFD7TA73I6wI+0oO9qOsWPtODveTrAT7SQ72U6xU+00O93OsDPtLDvbzrFz7Tw73y6wC+0iu9gusUvtMrvcrrAr7Sq72q6xa+06u95usBvtJrvZbrFb7Ta73e6wO+0uu9vusXvtPrvfHrAH7SF72B6xR+0xe9yesCftKfvsb4/A+ef2rx8gFXlGJVRGFVRFNVRHDdRELdRGHdRFPdRHg8gbX+SNz4bayBtfeP9rN77Tnp+xZ+05e95esBftJXvZXrFX7TV73d6wN+0te9vesXftPXvfPrAP7SP72D6xEf+ARHhqAwtQoME2io1qo9noNoaNaWPZ2DaOjWvj2fg2gU1oQ2wim9gmsUltMpvcprApbSqb2qaxaW06m95msBltJpvZZrFZbTab3eawOW0um9vmsXltPpvfFrAFbSFb2BaxRW0xW9yWsCVtKVvalrFlbTlb3lawoRHzDwo//n7jC372xhe4UMlWtlVsVVvNVrc1bE1by9a2dWxdW8/Wtw0iPii+joacN0JjNEFTNENztEBLtEJrtEFbtEN7dAgOf8N+7iN374L+/7t3kbt1z2e3LrBQBBaJf7ojF7kD93x24CKOf2td/ROKWJ6DKhkAAA== \ No newline at end of file +H4sIAAAAAAAA/+3YY4xkaRhA4e6xp8e2bavHtj2ztjG2bdu2bWttjm3P9uyp9OnNZP/uJrOb9E2enNxblU5V3qrvVn8dg4OCYgaFH9HtB5aHgqIgKqL5eIyg8OfHQmzEQVzEQ3wkQEKEIBESIwmSIhmSIwVSIhVSIw3SIh3SIwMyIhMyIwuyIhuyIwdyIhdyIw/yIh/yowAKohAKowiKohiKowRKohRKowzKohzKowJCURGVUBlVUBXVUB01UBO1UBt1UBf1UB8N0BCN0BhN0BTN0Bwt0BKt0Bpt0Bbt0B4d0BEv4EW8hJfxCl7Fa3gdb+BNvIW38Q7exXt431lGd5btnOuH+Agf4xN8ik7ojC7oim7ojh7oiV7ojT7oi37ojwEYiEEYjCEYimEYjhEYiVEYjTEYi3EYjwmYiEmYjCmYimmYjhmYiVmYjTmYi3mYjwVYiEVYjCVYimVYjhVYiVVYjTVYi3VYjw3YiE3YjC3Yim3Yjh3YiV3YjT3Yi33YjwM4iEM4jCM4imM4jhM4iVPOIYqzCByfeS3w/Qrx2hf4El/ha3yDb/EdvscP+BE/4Wf8gl/xG3737wW+qxGzPo0zOItzOI8LuIhLuIwruIpruI4buIlbuI07uIt7uI8HeIhHeIwn+ANheBoU/gaDEQVREQ3RESOw1iAWYiMO4iIe4iMBEiIEiZAYSZAUyZAcKZASqZAaaZAW6ZAeGZARmZAZWZAV2ZAdOZATuZAbeZAX+ZAfBVAQhVAYRVAUxVAcJVASpVAaZVAW5VAeFRAaHD7jwHr47Foa5vzDnHmYswpzboHGsDFtLBvbxrFxbTwb3yawCW2ITWQT2yQ2qU1mk9sUNqVNZVPbNDatTWfT2ww2o81kM9ssNqvNZrPbHDanzWVz2zw2r81n89sCtqAtZAvbIraoLWaL2xK2pC1lS9sytqwtZ8vbCjbUVrSVbGVbxVa11Wx1W8PWtLVsbVvH1rX1bH3bwDa0jWxj28Q2tc1sc9vCtrStbGvbxra17Wx728F2tC/YF+1L9mX7in3VvmZft2/YN+1b9m37jn3Xvmfftx888zoDx4eef2Q/tp/YT20n29l2sV1tN9vd9rA9bS/b2/axfW0/298OsAPtIDvYDrFD7TA73I6wI+0oO9qOsWPtODveTrAT7SQ72U6xU+00O93OsDPtLDvbzrFz7Tw73y6wC+0iu9gusUvtMrvcrrAr7Sq72q6xa+06u95usBvtJrvZbrFb7Ta73e6wO+0uu9vusXvtPrvfHrAH7SF72B6xR+0xe9yesCftKfvsb4/A+ef2rx8gFXlGJVRGFVRFNVRHDdRELdRGHdRFPdRHg8gbX+SNz4bayBtfeP9rN77Tnp+xZ+05e95esBftJXvZXrFX7TV73d6wN+0te9vesXftPXvfPrAP7SP72D6xEf+ARHhqAwtQoME2io1qo9noNoaNaWPZ2DaOjWvj2fg2gU1oQ2wim9gmsUltMpvcprApbSqb2qaxaW06m95msBltJpvZZrFZbTab3eawOW0um9vmsXltPpvfFrAFbSFb2BaxRW0xW9yWsCVtKVvalrFlbTlb3lawoRHzDwo//n7jC372xhe4UMlWtlVsVVvNVrc1bE1by9a2dWxdW8/Wtw0iPii+joacN0JjNEFTNENztEBLtEJrtEFbtEN7dAgOf8N+7iN374L+/7t3kbt1z2e3LrBQBBaJf7ojF7kD93x24CKOf2td/ROKWJ6DKhkAAA== diff --git a/circuits/cpp/barretenberg/ts/bin-test/target/main.json b/circuits/cpp/barretenberg/ts/bin-test/target/main.json new file mode 100644 index 000000000000..d4233e7c57b8 --- /dev/null +++ b/circuits/cpp/barretenberg/ts/bin-test/target/main.json @@ -0,0 +1 @@ +{"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"verification_key","type":{"kind":"array","length":114,"type":{"kind":"field"}},"visibility":"private"},{"name":"proof","type":{"kind":"array","length":94,"type":{"kind":"field"}},"visibility":"private"},{"name":"public_inputs","type":{"kind":"array","length":1,"type":{"kind":"field"}},"visibility":"private"},{"name":"key_hash","type":{"kind":"field"},"visibility":"private"},{"name":"input_aggregation_object","type":{"kind":"array","length":16,"type":{"kind":"field"}},"visibility":"private"},{"name":"proof_b","type":{"kind":"array","length":94,"type":{"kind":"field"}},"visibility":"private"}],"param_witnesses":{"input_aggregation_object":[211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226],"key_hash":[210],"proof":[115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208],"proof_b":[227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320],"public_inputs":[209],"verification_key":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114]},"return_type":{"kind":"array","length":16,"type":{"kind":"field"}},"return_witnesses":[337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352]},"bytecode":"H4sIAAAAAAAA/+3YY4xkaRhA4e6xp8e2bavHtj2ztjG2bdu2bWttjm3P9uyp9OnNZP/uJrOb9E2enNxblU5V3qrvVn8dg4OCYgaFH9HtB5aHgqIgKqL5eIyg8OfHQmzEQVzEQ3wkQEKEIBESIwmSIhmSIwVSIhVSIw3SIh3SIwMyIhMyIwuyIhuyIwdyIhdyIw/yIh/yowAKohAKowiKohiKowRKohRKowzKohzKowJCURGVUBlVUBXVUB01UBO1UBt1UBf1UB8N0BCN0BhN0BTN0Bwt0BKt0Bpt0Bbt0B4d0BEv4EW8hJfxCl7Fa3gdb+BNvIW38Q7exXt431lGd5btnOuH+Agf4xN8ik7ojC7oim7ojh7oiV7ojT7oi37ojwEYiEEYjCEYimEYjhEYiVEYjTEYi3EYjwmYiEmYjCmYimmYjhmYiVmYjTmYi3mYjwVYiEVYjCVYimVYjhVYiVVYjTVYi3VYjw3YiE3YjC3Yim3Yjh3YiV3YjT3Yi33YjwM4iEM4jCM4imM4jhM4iVPOIYqzCByfeS3w/Qrx2hf4El/ha3yDb/EdvscP+BE/4Wf8gl/xG3737wW+qxGzPo0zOItzOI8LuIhLuIwruIpruI4buIlbuI07uIt7uI8HeIhHeIwn+ANheBoU/gaDEQVREQ3RESOw1iAWYiMO4iIe4iMBEiIEiZAYSZAUyZAcKZASqZAaaZAW6ZAeGZARmZAZWZAV2ZAdOZATuZAbeZAX+ZAfBVAQhVAYRVAUxVAcJVASpVAaZVAW5VAeFRAaHD7jwHr47Foa5vzDnHmYswpzboHGsDFtLBvbxrFxbTwb3yawCW2ITWQT2yQ2qU1mk9sUNqVNZVPbNDatTWfT2ww2o81kM9ssNqvNZrPbHDanzWVz2zw2r81n89sCtqAtZAvbIraoLWaL2xK2pC1lS9sytqwtZ8vbCjbUVrSVbGVbxVa11Wx1W8PWtLVsbVvH1rX1bH3bwDa0jWxj28Q2tc1sc9vCtrStbGvbxra17Wx728F2tC/YF+1L9mX7in3VvmZft2/YN+1b9m37jn3Xvmfftx888zoDx4eef2Q/tp/YT20n29l2sV1tN9vd9rA9bS/b2/axfW0/298OsAPtIDvYDrFD7TA73I6wI+0oO9qOsWPtODveTrAT7SQ72U6xU+00O93OsDPtLDvbzrFz7Tw73y6wC+0iu9gusUvtMrvcrrAr7Sq72q6xa+06u95usBvtJrvZbrFb7Ta73e6wO+0uu9vusXvtPrvfHrAH7SF72B6xR+0xe9yesCftKfvsb4/A+ef2rx8gFXlGJVRGFVRFNVRHDdRELdRGHdRFPdRHg8gbX+SNz4bayBtfeP9rN77Tnp+xZ+05e95esBftJXvZXrFX7TV73d6wN+0te9vesXftPXvfPrAP7SP72D6xEf+ARHhqAwtQoME2io1qo9noNoaNaWPZ2DaOjWvj2fg2gU1oQ2wim9gmsUltMpvcprApbSqb2qaxaW06m95msBltJpvZZrFZbTab3eawOW0um9vmsXltPpvfFrAFbSFb2BaxRW0xW9yWsCVtKVvalrFlbTlb3lawoRHzDwo//n7jC372xhe4UMlWtlVsVVvNVrc1bE1by9a2dWxdW8/Wtw0iPii+joacN0JjNEFTNENztEBLtEJrtEFbtEN7dAgOf8N+7iN374L+/7t3kbt1z2e3LrBQBBaJf7ojF7kD93x24CKOf2td/ROKWJ6DKhkAAA==","proving_key":null,"verification_key":null} \ No newline at end of file diff --git a/circuits/cpp/barretenberg/ts/bin-test/test.js b/circuits/cpp/barretenberg/ts/bin-test/test.js new file mode 100755 index 000000000000..8f75c7303a16 --- /dev/null +++ b/circuits/cpp/barretenberg/ts/bin-test/test.js @@ -0,0 +1,153 @@ +#!/usr/bin/env node + +import assert from 'node:assert'; +import fs from 'fs'; +import { fileURLToPath } from 'url'; +import path from 'node:path'; +import { describe, it, before } from 'node:test'; + +import { exec } from 'node:child_process'; + +const scriptDirectory = getScriptDirectory(); +const executableScriptLocation = '../dest/node/main.js'; +const executionScript = path.join(scriptDirectory, executableScriptLocation); +const compiledNoirProgramLocation = path.join(scriptDirectory, 'target/main.json'); +const solvedWitnessLocation = path.join(scriptDirectory, 'target/witness.tr'); +const expectedBarretenbergWasmLocation = path.join(scriptDirectory, '../dest/barretenberg.wasm'); +const expectedBarretenbergWasmThreadsLocation = path.join(scriptDirectory, '../dest/barretenberg-threads.wasm'); +const possibleBarretenbergWasmLocation = path.join(scriptDirectory, '../../cpp/build-wasm/bin/barretenberg.wasm'); +const possibleBarretenbergWasmThreadsLocation = path.join( + scriptDirectory, + '../../cpp/build-wasm-threads/bin/barretenberg.wasm', +); + +// Skips warnings, ie. experimental features +process.removeAllListeners('warning'); + +function getScriptDirectory() { + const moduleURL = import.meta.url; + const modulePath = fileURLToPath(moduleURL); + const scriptDirectory = path.dirname(modulePath); + + return scriptDirectory; +} + +function copyBBWASMIfNotPresent(expectedLocation, possibleBuildLocation) { + if (!fs.existsSync(expectedLocation)) { + try { + fs.copyFileSync(possibleBuildLocation, expectedLocation); + console.log(`${possibleBuildLocation} copied to ${expectedLocation}`); + } catch (error) { + console.error(`Error copying file ${possibleBuildLocation} to ${expectedLocation}:`, error); + console.error('Have you build with `yarn build` ?'); + throw error; + } + } +} + +function throwMissingFile(filePath, message) { + const fileExists = fs.existsSync(filePath); + if (!fileExists) { + console.error(`File does not exist at ${filePath}, ${message}.`); + throw Error(`File does not exist at ${filePath}, ${message}.`); + } +} + +function checkArtifactsPresent() { + copyBBWASMIfNotPresent(expectedBarretenbergWasmLocation, possibleBarretenbergWasmLocation); + copyBBWASMIfNotPresent(expectedBarretenbergWasmThreadsLocation, possibleBarretenbergWasmThreadsLocation); + + throwMissingFile(executionScript, "execute 'yarn build:ts:node' first"); + + throwMissingFile(compiledNoirProgramLocation, "execute 'nargo compile' first"); + + throwMissingFile(solvedWitnessLocation, "execute 'nargo execute' first"); +} + +function executeBBCli(command) { + // const extendedEnv = Object.assign({}, process.env, { + // DEBUG: '*', + // }); + // exec( + // command, + // { + // cwd: scriptDirectory, + // // env: extendedEnv, + // }, + // function (error, stdout, stderr) { + // if (error) { + // done(error); + // return; + // } + + // // Assert that the stdout matches the expected output template + // assert.match(stdout.trim(), expectedOutputTemplate); + + // // Since no error from execution and assert matched expected template + // // this is now understood as correct execution. + // done(); + // }, + // ); + + return new Promise((resolve, reject) => { + const childProcess = exec( + command, + { + cwd: scriptDirectory, + // env: extendedEnv, + }, + (error, stdout, stderr) => { + if (error) { + reject(error); + } else { + resolve({ stdout, stderr }); + } + }, + ); + + childProcess.on('exit', code => { + if (code !== 0) { + reject(new Error(`Command '${command}' exited with code ${code}`)); + } + }); + }); +} + +describe('Test bb subcommands', () => { + before(checkArtifactsPresent); + + it('get gate count using `bb gates` command', async () => { + const expectedOutputTemplate = /^\d+$/gm; + const command = `${executionScript} gates`; + + const {stdout, stderr} = await executeBBCli(command); + assert.match(stdout.trim(), expectedOutputTemplate); + + }); + + it('creates proof with `bb prove -o proof` command', async () => { + // We expect any character stream since binary print is result of this command + const expectedOutputTemplate = /.+/; + const command = `${executionScript} prove -o proof`; + + const {stdout, stderr} = await executeBBCli(command); + assert.match(stdout.trim(), expectedOutputTemplate); + }); + + it('writes verification key with `bb write_vk -o vk` command', async () => { + // We expect any character stream since binary print is result of this command + const expectedOutputTemplate = /.+/; + const command = `${executionScript} write_vk -o vk`; + + const {stdout, stderr} = await executeBBCli(command); + assert.match(stdout.trim(), expectedOutputTemplate); + }); + + it('verifies proof with `bb verify -k vk -p proof` command', async () => { + const expectedOutputTemplate = /true/; + const command = `${executionScript} verify -k vk -p proof`; + + const {stdout, stderr} = await executeBBCli(command); + assert.match(stdout.trim(), expectedOutputTemplate); + }); +}); diff --git a/circuits/cpp/barretenberg/ts/package.json b/circuits/cpp/barretenberg/ts/package.json index 8518682c056c..93179c1f42da 100644 --- a/circuits/cpp/barretenberg/ts/package.json +++ b/circuits/cpp/barretenberg/ts/package.json @@ -21,9 +21,10 @@ ], "scripts": { "clean": "rm -rf ./dest .tsbuildinfo.browser .tsbuildinfo.node", - "build": "yarn clean && yarn build:wasm && yarn build:ts:browser && yarn build:ts:node", + "build": "yarn clean && yarn build:wasm && yarn copy_wasm_dest && yarn build:ts:browser && yarn build:ts:node", "build:dev": "tsc -b --watch", "build:wasm": "cd ../cpp && cmake --preset wasm-threads && cmake --build --preset wasm-threads && cmake --preset wasm && cmake --build --preset wasm", + "copy_wasm_dest": "cp ../cpp/build-wasm/bin/barretenberg.wasm ./dest/ && cp ../cpp/build-wasm-threads/bin/barretenberg.wasm ./dest/barretenberg-threads.wasm", "build:ts:browser": "tsc -b tsconfig.browser.json && BUILD_TARGET=browser webpack && chmod +x ./dest/browser/main.js && BUILD_TARGET=browser node replace_imports.cjs", "build:ts:node": "tsc -b tsconfig.node.json && chmod +x ./dest/node/main.js && BUILD_TARGET=node node replace_imports.cjs", "build:bindings": "cd .. && ./scripts/bindgen.sh", @@ -32,7 +33,7 @@ "formatting:fix": "prettier -w ./src", "test": "yarn build:ts:browser && yarn build:ts:node && yarn test:jest && yarn test:bin", "test:jest": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests", - "test:bin": "cd ./bin-test && ./bin-test.sh", + "test:bin": "bin-test/test.js", "test-debug": "NODE_NO_WARNINGS=1 node --inspect-brk=0.0.0.0 --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests --runInBand", "prepack": "yarn build", "deploy": "npm publish --access public"