pull/5228/head
bunsenstraat 2 months ago committed by bunsenstraat
parent 8bca72cb22
commit ef2b78c1e5
  1. 12
      .circleci/config.yml
  2. 2
      apps/circuit-compiler/src/app/components/generateProof.tsx
  3. 9
      apps/remixdesktop/src/plugins/circomElectronBasePlugin.ts
  4. 60
      apps/remixdesktop/src/tools/circom.ts
  5. 86
      apps/remixdesktop/test/tests/app/circom-compiler.test.ts
  6. 67
      apps/remixdesktop/test/tests/app/circom-script.test.ts

@ -107,23 +107,22 @@ jobs:
test-remixdesktop-linux:
machine:
image: ubuntu-2004:current
image: ubuntu-2204:current
resource_class:
xlarge
working_directory: ~/remix-project
parallelism: 15
steps:
- run: ldd --version
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/desktopbuild.zip
- run:
command: |
nvm install 20.2
nvm use 20.2
node -v
npm install --global yarn node-gyp
sudo npm install --global yarn node-gyp
python -m pip install --upgrade pip
pip install setuptools
mkdir apps/remixdesktop/build
@ -136,14 +135,14 @@ jobs:
- run:
name: "Run tests"
command: |
nvm use 20.2
cd apps/remixdesktop/
nvm use 20.2
./run_ci_test.sh
- run:
name: "Run isogit tests"
command: |
nvm use 20.2
cd apps/remixdesktop/
nvm use 20.2
./run_git_ui_isogit_tests.sh
- store_test_results:
path: ./apps/remixdesktop/reports/tests
@ -521,6 +520,7 @@ jobs:
ls -la dist/apps/remix-ide
nvm install 20.2
nvm use 20.2
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
- restore_cache:
keys:
- remixdesktop-deps-mac-{{ checksum "apps/remixdesktop/yarn.lock" }}

@ -27,7 +27,7 @@ export function GenerateProof () {
className="btn btn-secondary btn-block d-block w-100 text-break mb-1 mt-1"
onClick={() => generateProof(circuitApp.plugin, circuitApp.appState, circuitApp.dispatch)}
disabled={(status === "compiling") || (status === "computing") || (status === "proving") || (status === "exporting")}
data-id="compute_witness_btn"
data-id="generateProofBtn"
>
<RenderIf condition={status === 'proving'}>
<i className="fas fa-sync fa-spin mr-2" aria-hidden="true"></i>

@ -35,6 +35,8 @@ class CircomElectronPluginClient extends ElectronBasePluginClient {
}
async install(version = 'latest') {
this.call('terminal' as any, 'logHtml', `Checking if circom compiler (${version}) is installed in ${getInstallationPath(version)}`)
this.isCircomInstalled = await circomCli.isCircomInstalled(version)
if (!this.isCircomInstalled) {
this.call('terminal' as any, 'logHtml', 'Downloading circom compiler from ' + getInstallationUrl(version))
@ -56,8 +58,11 @@ class CircomElectronPluginClient extends ElectronBasePluginClient {
else {
// @ts-ignore
if (process.platform === 'win32' && 'wasm' in options) {
// @ts-ignore
await this.call('fs', 'rmdir', path.join(extractParentFromKey(filePath), '.bin', extractNameFromKey(filePath).replace('.circom', '_js')))
try{
// @ts-ignore
await this.call('fs', 'rmdir', path.join(extractParentFromKey(filePath), '.bin', extractNameFromKey(filePath).replace('.circom', '_js')))
} catch (e) {
}
}
}
filePath = path.join(wd, filePath)

@ -1,4 +1,5 @@
import { app } from 'electron'
import os from 'os'
import { exec } from 'child_process'
import path from 'path'
import fs, { existsSync } from 'fs'
@ -33,16 +34,13 @@ async function downloadFile(url: string, dest: string) {
}
export function getInstallationPath(version) {
switch (process.platform) {
case 'win32':
return process.env.NODE_ENV === 'production' ? path.join(app.getPath('temp'), 'circom-download', version, 'circom-windows-amd64.exe') : path.join(app.getAppPath(), 'circom-download', version, 'circom-windows-amd64.exe')
case 'darwin':
return process.env.NODE_ENV === 'production' ? path.join(app.getPath('temp'), 'circom-download', version, 'circom-macos-amd64') : path.join(app.getAppPath(), 'circom-download', version, 'circom-macos-amd64')
case 'linux':
return process.env.NODE_ENV === 'production' ? path.join(app.getPath('temp'), 'circom-download', version, 'circom-linux-amd64') : path.join(app.getAppPath(), 'circom-download', version, 'circom-linux-amd64')
}
const fileNames = {
win32: 'circom-windows-amd64.exe',
darwin: 'circom-macos-amd64',
linux: 'circom-linux-amd64'
};
return path.join(os.tmpdir(), 'circom-download', version, fileNames[process.platform]);
}
export function getInstallationUrl(version) {
@ -59,25 +57,9 @@ export function getInstallationUrl(version) {
}
export function getLogInputSignalsPath() {
console.log('home: ', app.getPath('home'))
console.log('appData: ', app.getPath('appData'))
console.log('userData: ', app.getPath('userData'))
console.log('temp: ', app.getPath('temp'))
console.log('exe: ', app.getPath('exe'))
console.log('getAppPath: ', app.getAppPath())
switch (process.platform) {
case 'win32':
// eslint-disable-next-line no-case-declarations
const programDir = app.getPath('exe').split('\\').slice(0, -1).join('\\')
return process.env.NODE_ENV === 'production' ? path.join(programDir, 'log_input_signals.txt') : path.join(app.getAppPath(), 'log_input_signals.txt')
case 'darwin':
return path.join(app.getAppPath(), 'log_input_signals.txt')
case 'linux':
return process.env.NODE_ENV === 'production' ? path.join(app.getPath('temp'), 'log_input_signals.txt') : path.join(app.getAppPath(), 'log_input_signals.txt')
}
const tempFilePath = path.join(os.tmpdir(), 'log_input_signals.txt');
return tempFilePath;
}
export const circomCli = {
@ -106,9 +88,15 @@ export const circomCli = {
async run (filePath: string, version: string, options?: Record<string, string>) {
const installationPath = getInstallationPath(version)
const cmd = `${installationPath} ${filePath} ${Object.keys(options || {}).map((key) => options[key] ? `--${key} ${options[key]}` : `--${key}`).join(' ')}`
console.log(cmd)
if(process.platform === 'darwin') {
const rosettaInstalled = await checkRosettaInstalled();
if(rosettaInstalled === 'Rosetta is not installed') {
throw new Error('Rosetta is not installed. Please install Rosetta to run this command.');
}
}
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
exec(cmd, { cwd: os.tmpdir() }, (error, stdout, stderr) => {
if (error) {
reject(`${error.message} with error code ${error.code}`)
} else {
@ -134,3 +122,15 @@ export const extractNameFromKey = (key: string): string => {
return keyPath[keyPath.length - 1]
}
async function checkRosettaInstalled(): Promise<string> {
return new Promise((resolve, reject) => {
exec("/usr/bin/pgrep oahd > /dev/null && echo 'Rosetta is installed' || echo 'Rosetta is not installed'", (error, stdout, stderr) => {
if (error) {
reject(`Error: ${stderr}`);
} else {
resolve(stdout.trim());
}
});
});
}

@ -0,0 +1,86 @@
import { NightwatchBrowser } from "nightwatch"
const tests = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
browser.hideToolTips()
done()
},
'Should create semaphore workspace': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="homeTabGetStartedsemaphore"]', 20000)
.click('*[data-id="homeTabGetStartedsemaphore"]')
.pause(3000)
.windowHandles(function (result) {
console.log(result.value)
browser.switchWindow(result.value[1])
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcircuits"]')
.click('*[data-id="treeViewLitreeViewItemcircuits"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcircuits/semaphore.circom"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.click('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/groth16"]')
.click('*[data-id="treeViewLitreeViewItemscripts/groth16"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/groth16/groth16_trusted_setup.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/groth16/groth16_zkproof.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk"]')
.click('*[data-id="treeViewLitreeViewItemscripts/plonk"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/plonk_trusted_setup.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/plonk_zkproof.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtemplates"]')
.click('*[data-id="treeViewLitreeViewItemtemplates"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtemplates/groth16_verifier.sol.ejs"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtemplates/plonk_verifier.sol.ejs"]')
})
},
'Should compile a simple circuit using editor play button': function (browser: NightwatchBrowser) {
browser
.click('[data-id="treeViewLitreeViewItemcircuits/simple.circom"]')
.waitForElementVisible('[data-id="play-editor"]')
.click('[data-id="play-editor"]')
.pause(3000)
.click('[data-id="play-editor"]')
.waitForElementVisible('[data-id="verticalIconsKindcircuit-compiler"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcircuits/.bin"]')
.click('[data-id="treeViewLitreeViewItemcircuits/.bin"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcircuits/.bin/simple_js"]')
.click('[data-id="treeViewLitreeViewItemcircuits/.bin/simple_js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcircuits/.bin/simple_js/simple.wasm"]')
},
'Should run setup script for simple circuit': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('circuit-compiler')
.frame(0)
.waitForElementVisible('[data-id="runSetupBtn"]')
.click('[data-id="runSetupBtn"]')
},
'Should compute a witness for a simple circuit': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="compute_witness_btn"]', 60000)
.waitForElementVisible('[data-id="circuit_input_a"]')
.waitForElementVisible('[data-id="circuit_input_b"]')
.setValue('[data-id="circuit_input_a"]', '1')
.setValue('[data-id="circuit_input_b"]', '2')
.click('[data-id="compute_witness_btn"]')
.frameParent()
.clickLaunchIcon('filePanel')
.waitForElementPresent('[data-id="treeViewLitreeViewItemcircuits/.bin/simple_js/simple.wtn"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcircuits/.bin/simple_js/simple.wtn"]')
},
'Should generate proof for a simple circuit': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('circuit-compiler')
.frame(0)
.waitForElementVisible('[data-id="generateProofBtn"]')
.click('[data-id="generateProofBtn"]')
.frameParent()
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//span[@class='text-log' and contains(., 'zk proof validity true')]",
timeout: 60000
})
}
}
module.exports = tests

@ -0,0 +1,67 @@
import { NightwatchBrowser } from "nightwatch"
const tests = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
browser.hideToolTips()
done()
},
'Should create semaphore workspace': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="homeTabGetStartedsemaphore"]', 20000)
.click('*[data-id="homeTabGetStartedsemaphore"]')
.pause(3000)
.windowHandles(function (result) {
console.log(result.value)
browser.switchWindow(result.value[1])
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcircuits"]')
.click('*[data-id="treeViewLitreeViewItemcircuits"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcircuits/semaphore.circom"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.click('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/groth16"]')
.click('*[data-id="treeViewLitreeViewItemscripts/groth16"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/groth16/groth16_trusted_setup.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/groth16/groth16_zkproof.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk"]')
.click('*[data-id="treeViewLitreeViewItemscripts/plonk"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/plonk_trusted_setup.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/plonk_zkproof.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtemplates"]')
.click('*[data-id="treeViewLitreeViewItemtemplates"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtemplates/groth16_verifier.sol.ejs"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtemplates/plonk_verifier.sol.ejs"]')
})
},
'Should run plonk trusted setup script for hash checker #group6': function (browser: NightwatchBrowser) {
browser
.click('[data-id="treeViewLitreeViewItemscripts/plonk/plonk_trusted_setup.ts"]')
.pause(2000)
.click('[data-id="play-editor"]')
.waitForElementVisible('[data-id="verticalIconsKindcircuit-compiler"]')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//span[@class='text-log' and contains(., 'setup done.')]",
timeout: 60000
})
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/zk"]')
.click('*[data-id="treeViewLitreeViewItemscripts/plonk/zk"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/zk/keys"]')
.click('*[data-id="treeViewLitreeViewItemscripts/plonk/zk/keys"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/plonk/zk/keys/verification_key.json"]')
},
'Should run plonk zkproof script for hash checker #group6': function (browser: NightwatchBrowser) {
browser
.click('[data-id="treeViewLitreeViewItemscripts/plonk/plonk_zkproof.ts"]')
.pause(2000)
.click('[data-id="play-editor"]')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//span[@class='text-log' and contains(., 'proof done')]",
timeout: 60000
})
}
}
module.exports = {}
Loading…
Cancel
Save