Re-order feedback alert and abstract r1cs function

pull/5043/head
ioedeveloper 4 months ago
parent cfbd977225
commit 026443ab5e
  1. 17
      apps/circuit-compiler/src/app/actions/index.ts
  2. 11
      apps/circuit-compiler/src/app/app.tsx
  3. 5
      apps/circuit-compiler/src/app/components/compileBtn.tsx
  4. 20
      apps/circuit-compiler/src/app/components/container.tsx
  5. 86
      apps/circuit-compiler/src/app/components/feedback.tsx
  6. 14
      apps/circuit-compiler/src/app/components/setupExports.tsx
  7. 8
      apps/circuit-compiler/src/app/components/setupExportsBtn.tsx
  8. 9
      apps/circuit-compiler/src/app/components/witness.tsx
  9. 18
      apps/circuit-compiler/src/app/reducers/state.ts
  10. 10
      apps/circuit-compiler/src/app/services/circomPluginClient.ts
  11. 10
      apps/circuit-compiler/src/app/types/index.ts
  12. 2
      apps/circuit-compiler/src/css/app.css
  13. 2
      apps/circuit-compiler/src/profile.json

@ -12,24 +12,12 @@ export const compileCircuit = async (plugin: CircomPluginClient, appState: AppSt
console.log('Existing circuit compilation in progress')
}
} catch (e) {
plugin.emit('statusChanged', { key: 'error', title: e.message, type: 'error' })
plugin.internalEvents.emit('circuit_compiling_errored', e)
console.error(e)
}
}
export const generateR1cs = async (plugin: CircomPluginClient, appState: AppState) => {
try {
if (appState.status !== "generating") {
await plugin.generateR1cs(appState.filePath, { version: appState.version, prime: appState.primeValue })
} else {
console.log('Existing r1cs generation in progress')
}
} catch (e) {
plugin.internalEvents.emit('circuit_generating_r1cs_errored', e)
console.error('Generating R1CS failed: ', e)
}
}
export const computeWitness = async (plugin: CircomPluginClient, status: string, witnessValues: Record<string, string>) => {
try {
if (status !== "computing") {
@ -40,6 +28,7 @@ export const computeWitness = async (plugin: CircomPluginClient, status: string,
console.log('Existing witness computation in progress')
}
} catch (e) {
plugin.emit('statusChanged', { key: 'error', title: e.message, type: 'error' })
plugin.internalEvents.emit('circuit_computing_witness_errored', e)
console.error('Computing witness failed: ', e)
}
@ -47,7 +36,7 @@ export const computeWitness = async (plugin: CircomPluginClient, status: string,
export const runSetupAndExport = async (plugin: CircomPluginClient, appState: AppState) => {
const ptau_final = `https://ipfs-cluster.ethdevops.io/ipfs/${appState.ptauList.find(ptau => ptau.name === appState.ptauValue)?.ipfsHash}`
if (appState.status !== "generating") await plugin.generateR1cs(appState.filePath, { version: appState.version, prime: appState.primeValue })
await plugin.generateR1cs(appState.filePath, { version: appState.version, prime: appState.primeValue })
const fileName = extractNameFromKey(appState.filePath)
const readPath = extractParentFromKey(appState.filePath) + `/.bin/${fileName.replace('.circom', '.r1cs')}`

@ -50,16 +50,11 @@ function App() {
})
plugin.internalEvents.on('circuit_compiling_errored', compilerErrored)
// r1cs events
plugin.internalEvents.on('circuit_generating_r1cs_start', () => dispatch({ type: 'SET_COMPILER_STATUS', payload: 'generating' }))
plugin.internalEvents.on('circuit_generating_r1cs_done', () => dispatch({ type: 'SET_COMPILER_STATUS', payload: 'idle' }))
plugin.internalEvents.on('circuit_generating_r1cs_errored', compilerErrored)
// witness events
plugin.internalEvents.on('circuit_computing_witness_start', () => dispatch({ type: 'SET_COMPILER_STATUS', payload: 'computing' }))
plugin.internalEvents.on('circuit_computing_witness_done', () => {
dispatch({ type: 'SET_COMPILER_STATUS', payload: 'idle' })
dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: null })
dispatch({ type: 'SET_COMPUTE_FEEDBACK', payload: null })
})
plugin.internalEvents.on('circuit_computing_witness_errored', compilerErrored)
@ -118,9 +113,9 @@ function App() {
try {
const report = JSON.parse(err.message)
dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: report })
dispatch({ type: 'SET_COMPUTE_FEEDBACK', payload: report })
} catch (e) {
dispatch({ type: 'SET_COMPILER_FEEDBACK', payload: err.message })
dispatch({ type: 'SET_COMPUTE_FEEDBACK', payload: err.message })
}
}

@ -22,16 +22,13 @@ export function CompileBtn () {
<button
className="btn btn-primary btn-block d-block w-100 text-break mb-1 mt-1"
onClick={() => { compileCircuit(plugin, appState) }}
disabled={(appState.filePath === "") || (appState.status === "compiling") || (appState.status === "generating")}
disabled={(appState.filePath === "") || (appState.status === "compiling")}
data-id="compile_circuit_btn"
>
<div className="d-flex align-items-center justify-content-center">
<RenderIf condition={appState.status === 'compiling'}>
<i className="fas fa-sync fa-spin mr-2" aria-hidden="true"></i>
</RenderIf>
<RenderIfNot condition={appState.status === 'compiling'}>
<i className="fas fa-sync mr-2" aria-hidden="true"></i>
</RenderIfNot>
<div className="text-truncate overflow-hidden text-nowrap">
<span>
<FormattedMessage id="circuit.compile" />

@ -117,19 +117,29 @@ export function Container () {
<Configurations setPrimeValue={handlePrimeChange} primeValue={circuitApp.appState.primeValue} versionValue={circuitApp.appState.version} />
</Toggler>
<CircuitActions />
<RenderIf condition={circuitApp.appState.status !== 'compiling'}>
<CompilerFeedback feedback={circuitApp.appState.compilerFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} />
</RenderIf>
<RenderIf condition={circuitApp.appState.signalInputs.length > 0}>
<Toggler title='circuit.setupExports' dataId='setup_exports_toggler' show={true}>
<SetupExports />
<>
<SetupExports />
<RenderIf condition={circuitApp.appState.status !== 'exporting'}>
<CompilerFeedback feedback={circuitApp.appState.setupExportFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} />
</RenderIf>
</>
</Toggler>
</RenderIf>
<RenderIf condition={circuitApp.appState.signalInputs.length > 0}>
<Toggler title='circuit.computeWitness' dataId='witness_toggler'>
<WitnessSection plugin={circuitApp.plugin} signalInputs={circuitApp.appState.signalInputs} status={circuitApp.appState.status} />
<>
<WitnessSection plugin={circuitApp.plugin} signalInputs={circuitApp.appState.signalInputs} status={circuitApp.appState.status} />
<RenderIf condition={circuitApp.appState.status !== 'computing'}>
<CompilerFeedback feedback={circuitApp.appState.computeFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} />
</RenderIf>
</>
</Toggler>
</RenderIf>
<RenderIf condition={(circuitApp.appState.status !== 'compiling') && (circuitApp.appState.status !== 'computing') && (circuitApp.appState.status !== 'generating')}>
<CompilerFeedback feedback={circuitApp.appState.feedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} />
</RenderIf>
</div>
</div>
</article>

@ -1,11 +1,11 @@
import { useState } from 'react'
import { CompilerFeedbackProps, CompilerReport } from '../types'
import { RenderIf } from '@remix-ui/helper'
import {CopyToClipboard} from '@remix-ui/clipboard'
import { CopyToClipboard } from '@remix-ui/clipboard'
import { FeedbackAlert } from './feedbackAlert'
export function CompilerFeedback ({ feedback, filePathToId, hideWarnings, openErrorLocation, askGPT }: CompilerFeedbackProps) {
const [ showException, setShowException ] = useState<boolean>(true)
const [showException, setShowException] = useState<boolean>(true)
const handleCloseException = () => {
setShowException(false)
@ -23,46 +23,50 @@ export function CompilerFeedback ({ feedback, filePathToId, hideWarnings, openEr
return (
<div>
<div className="circuit_errors_box py-4">
<RenderIf condition={ (typeof feedback === "string") && showException }>
<div className="circuit_feedback error alert alert-danger" data-id="circuit_feedback">
<span> <>{ feedback }</> </span>
<div className="close" data-id="renderer" onClick={handleCloseException}>
<i className="fas fa-times"></i>
</div>
<div className="d-flex pt-1 flex-row-reverse">
<span className="ml-3 pt-1 py-1" >
<CopyToClipboard content={feedback} className="p-0 m-0 far fa-copy error" direction={'top'} />
</span>
</div>
</div>
</RenderIf>
<RenderIf condition={ Array.isArray(feedback) }>
<>
{
Array.isArray(feedback) && feedback.map((response, index) => (
<div key={index} onClick={() => handleOpenError(response)}>
<RenderIf condition={response.type === 'Error'}>
<div className={`circuit_feedback ${response.type.toLowerCase()} alert alert-danger`} data-id="circuit_feedback">
<FeedbackAlert
message={response.message + (response.labels[0] ? ": " + response.labels[0].message + ` ${filePathToId[response.labels[0].file_id]}:${response.labels[0].range.start}:${response.labels[0].range.end}` : '')}
askGPT={ () => handleAskGPT(response) } />
</div>
</RenderIf>
<RenderIf condition={(response.type === 'Warning') && !hideWarnings}>
<div className={`circuit_feedback ${response.type.toLowerCase()} alert alert-warning`} data-id="circuit_feedback">
<FeedbackAlert
message={response.message}
askGPT={() => { handleAskGPT(response) }} />
</div>
</RenderIf>
{
(feedback && typeof feedback === 'string') || (Array.isArray(feedback) && feedback.length > 0) ? (
<div className="circuit_errors_box">
<RenderIf condition={ (typeof feedback === "string") && showException }>
<div className="circuit_feedback error alert alert-danger" data-id="circuit_feedback">
<span> <>{ feedback }</> </span>
<div className="close" data-id="renderer" onClick={handleCloseException}>
<i className="fas fa-times"></i>
</div>
)
)
}
</>
</RenderIf>
</div>
<div className="d-flex pt-1 flex-row-reverse">
<span className="ml-3 pt-1 py-1" >
<CopyToClipboard content={feedback} className="p-0 m-0 far fa-copy error" direction={'top'} />
</span>
</div>
</div>
</RenderIf>
<RenderIf condition={ Array.isArray(feedback) }>
<>
{
Array.isArray(feedback) && feedback.map((response, index) => (
<div key={index} onClick={() => handleOpenError(response)}>
<RenderIf condition={response.type === 'Error'}>
<div className={`circuit_feedback ${response.type.toLowerCase()} alert alert-danger`} data-id="circuit_feedback">
<FeedbackAlert
message={response.message + (response.labels[0] ? ": " + response.labels[0].message + ` ${filePathToId[response.labels[0].file_id]}:${response.labels[0].range.start}:${response.labels[0].range.end}` : '')}
askGPT={ () => handleAskGPT(response) } />
</div>
</RenderIf>
<RenderIf condition={(response.type === 'Warning') && !hideWarnings}>
<div className={`circuit_feedback ${response.type.toLowerCase()} alert alert-warning`} data-id="circuit_feedback">
<FeedbackAlert
message={response.message}
askGPT={() => { handleAskGPT(response) }} />
</div>
</RenderIf>
</div>
)
)
}
</>
</RenderIf>
</div>
) : <></>
}
</div>
)
}

@ -16,6 +16,18 @@ export function SetupExports () {
// circuitApp.dispatch({ type: 'SET_RANDOM_BEACON', payload: value })
// }
const handleRunSetup = async () => {
try {
circuitApp.dispatch({ type: 'SET_COMPILER_STATUS', payload: 'exporting' })
await runSetupAndExport(circuitApp.plugin, circuitApp.appState)
circuitApp.dispatch({ type: 'SET_COMPILER_STATUS', payload: 'idle' })
} catch (e) {
circuitApp.dispatch({ type: 'SET_COMPILER_STATUS', payload: 'errored' })
circuitApp.dispatch({ type: 'SET_SETUP_EXPORT_FEEDBACK', payload: e.message })
console.error(e)
}
}
return (
<div className="flex-column">
<div className="flex-column d-flex">
@ -115,7 +127,7 @@ export function SetupExports () {
<FormattedMessage id="circuit.exportVerificationKey" />
</label>
</div>
<SetupExportsBtn handleRunSetup={() => runSetupAndExport(circuitApp.plugin, circuitApp.appState)} />
<SetupExportsBtn handleRunSetup={handleRunSetup} status={circuitApp.appState.status} />
</div>
</div>
</div>

@ -1,7 +1,8 @@
import { CustomTooltip } from "@remix-ui/helper"
import { CustomTooltip, RenderIf } from "@remix-ui/helper"
import { FormattedMessage } from "react-intl"
import { CompilerStatus } from "../types"
export function SetupExportsBtn ({ handleRunSetup }: { handleRunSetup: () => void }) {
export function SetupExportsBtn ({ handleRunSetup, status }: { handleRunSetup: () => Promise<void>, status: CompilerStatus }) {
return <button
className="btn btn-secondary btn-block d-block w-100 text-break mt-2"
onClick={handleRunSetup}
@ -18,6 +19,9 @@ export function SetupExportsBtn ({ handleRunSetup }: { handleRunSetup: () => voi
}
>
<div className="d-flex align-items-center justify-content-center">
<RenderIf condition={status === 'exporting'}>
<i className="fas fa-sync fa-spin mr-2" aria-hidden="true"></i>
</RenderIf>
<div className="text-truncate overflow-hidden text-nowrap">
<span>
<FormattedMessage id="circuit.runSetup" />

@ -34,7 +34,7 @@ export function WitnessSection ({ plugin, signalInputs, status }: {plugin: Circo
}
return (
<div className="pb-2 border-bottom flex-column">
<div className="border-bottom flex-column">
<div className="flex-column d-flex">
<RenderIf condition={signalInputs.length > 0}>
<>
@ -49,17 +49,14 @@ export function WitnessSection ({ plugin, signalInputs, status }: {plugin: Circo
))
}
<button
className="btn btn-sm btn-secondary"
className="btn btn-secondary btn-block d-block w-100 text-break mb-1 mt-1"
onClick={() => { computeWitness(plugin, status, witnessValues) }}
disabled={(status === "compiling") || (status === "generating") || (status === "computing")}
disabled={(status === "compiling") || (status === "computing")}
data-id="compute_witness_btn"
>
<RenderIf condition={status === 'computing'}>
<i className="fas fa-sync fa-spin mr-2" aria-hidden="true"></i>
</RenderIf>
<RenderIfNot condition={status === 'computing'}>
<i className="fas fa-sync mr-2" aria-hidden="true"></i>
</RenderIfNot>
<FormattedMessage id="circuit.compute" />
</button>
</>

@ -11,7 +11,9 @@ export const appInitialState: AppState = {
autoCompile: false,
hideWarnings: false,
signalInputs: [],
feedback: null,
compilerFeedback: null,
computeFeedback: null,
setupExportFeedback: null,
provingScheme: 'groth16',
ptauList: [
{
@ -83,7 +85,19 @@ export const appReducer = (state = appInitialState, action: Actions): AppState =
case 'SET_COMPILER_FEEDBACK':
return {
...state,
feedback: action.payload
compilerFeedback: action.payload
}
case 'SET_COMPUTE_FEEDBACK':
return {
...state,
computeFeedback: action.payload
}
case 'SET_SETUP_EXPORT_FEEDBACK':
return {
...state,
setupExportFeedback: action.payload
}
case 'SET_FILE_PATH_TO_ID':

@ -197,24 +197,15 @@ export class CircomPluginClient extends PluginClient {
}
async generateR1cs (path: string, compilationConfig?: CompilationConfig): Promise<void> {
this.internalEvents.emit('circuit_generating_r1cs_start')
this.emit('statusChanged', { key: 'loading', title: 'Generating...', type: 'info' })
// @ts-ignore
this.call('terminal', 'log', { type: 'log', value: 'Generating R1CS for ' + path })
const [parseErrors, filePathToId] = await this.parse(path)
if (parseErrors && (parseErrors.length > 0)) {
if (parseErrors[0].type === 'Error') {
this.internalEvents.emit('circuit_parsing_errored', parseErrors)
this.logCompilerReport(parseErrors)
return
} else if (parseErrors[0].type === 'Warning') {
this.internalEvents.emit('circuit_parsing_warning', parseErrors)
this.logCompilerReport(parseErrors)
}
} else {
this.internalEvents.emit('circuit_parsing_done', parseErrors, filePathToId)
this.emit('statusChanged', { key: 'succeed', title: 'r1cs generated successfully', type: 'success' })
}
if (compilationConfig) {
const { prime, version } = compilationConfig
@ -232,7 +223,6 @@ export class CircomPluginClient extends PluginClient {
this._paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation failed'])
throw new Error(r1csErrors)
} else {
this.internalEvents.emit('circuit_generating_r1cs_done')
const fileName = extractNameFromKey(path)
const writePath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'r1cs')

@ -2,7 +2,7 @@ import { compiler_list } from 'circom_wasm'
import { Dispatch } from 'react'
import type { CircomPluginClient } from '../services/circomPluginClient'
export type CompilerStatus = "compiling" | "generating" | "computing" | "idle" | "errored" | "warning"
export type CompilerStatus = "compiling" | "computing" | "idle" | "errored" | "warning" | "exporting"
export type ProvingScheme = 'groth16' | 'plonk'
@ -27,7 +27,9 @@ export interface ActionPayloadTypes {
SET_AUTO_COMPILE: boolean,
SET_HIDE_WARNINGS: boolean,
SET_SIGNAL_INPUTS: string[],
SET_COMPILER_FEEDBACK: string | CompilerReport[]
SET_COMPILER_FEEDBACK: string | CompilerReport[],
SET_COMPUTE_FEEDBACK: string | CompilerReport[],
SET_SETUP_EXPORT_FEEDBACK: string | CompilerReport[],
SET_FILE_PATH_TO_ID: Record<number, string>,
SET_PROVING_SCHEME: ProvingScheme,
SET_PTAU_VALUE: string,
@ -53,7 +55,9 @@ export interface AppState {
autoCompile: boolean,
hideWarnings: boolean,
signalInputs: string[],
feedback: string | CompilerReport[],
compilerFeedback: string | CompilerReport[],
computeFeedback: string | CompilerReport[],
setupExportFeedback: string | CompilerReport[],
provingScheme: ProvingScheme,
ptauList: Array<PtauFile>,
ptauValue: string,

@ -37,8 +37,6 @@ body {
text-transform: uppercase;
}
.circuit_errors_box {
padding-left: 5px;
padding-right: 5px;
word-break: break-word;
}
.circuit_feedback.success,

@ -4,7 +4,7 @@
"displayName": "Circom ZKP compiler",
"events": [],
"version": "2.0.0",
"methods": ["init", "parse", "compile", "generateR1cs"],
"methods": ["init", "parse", "compile"],
"canActivate": [],
"url": "",
"description": "Enables circuit compilation and computing a witness for ZK proofs",

Loading…
Cancel
Save