|
|
@ -4,7 +4,7 @@ import EventManager from 'events' |
|
|
|
import pathModule from 'path' |
|
|
|
import pathModule from 'path' |
|
|
|
import { parse, compile, generate_witness, generate_r1cs, compiler_list } from 'circom_wasm' |
|
|
|
import { parse, compile, generate_witness, generate_r1cs, compiler_list } from 'circom_wasm' |
|
|
|
import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper' |
|
|
|
import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper' |
|
|
|
import { CompilationConfig, CompilerReport } from '../types' |
|
|
|
import { CompilationConfig, CompilerReport, ResolverOutput } from '../types' |
|
|
|
|
|
|
|
|
|
|
|
export class CircomPluginClient extends PluginClient { |
|
|
|
export class CircomPluginClient extends PluginClient { |
|
|
|
public internalEvents: EventManager |
|
|
|
public internalEvents: EventManager |
|
|
@ -37,10 +37,7 @@ export class CircomPluginClient extends PluginClient { |
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
fileContent = await this.call('fileManager', 'readFile', path) |
|
|
|
fileContent = await this.call('fileManager', 'readFile', path) |
|
|
|
} |
|
|
|
} |
|
|
|
this.lastParsedFiles = { |
|
|
|
this.lastParsedFiles = await this.resolveDependencies(path, fileContent, { [path]: { content: fileContent, parent: null } }) |
|
|
|
[path]: fileContent, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.lastParsedFiles = await this.resolveDependencies(path, fileContent, this.lastParsedFiles) |
|
|
|
|
|
|
|
const parsedOutput = parse(path, this.lastParsedFiles) |
|
|
|
const parsedOutput = parse(path, this.lastParsedFiles) |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
@ -211,14 +208,13 @@ export class CircomPluginClient extends PluginClient { |
|
|
|
this.internalEvents.emit('circuit_computing_witness_done') |
|
|
|
this.internalEvents.emit('circuit_computing_witness_done') |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async resolveDependencies(filePath: string, fileContent: string, output = {}, depPath: string = '', blackPath: string[] = []): Promise<Record<string, string>> { |
|
|
|
async resolveDependencies(filePath: string, fileContent: string, output: ResolverOutput = {}, depPath: string = '', parent: string = ''): Promise<Record<string, string>> { |
|
|
|
// extract all includes
|
|
|
|
// extract all includes
|
|
|
|
const includes = (fileContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
|
|
|
const includes = (fileContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
|
|
|
|
|
|
|
|
|
|
|
await Promise.all( |
|
|
|
await Promise.all( |
|
|
|
includes.map(async (include) => { |
|
|
|
includes.map(async (include) => { |
|
|
|
// fix for endless recursive includes
|
|
|
|
// fix for endless recursive includes
|
|
|
|
if (blackPath.includes(include)) return |
|
|
|
|
|
|
|
let dependencyContent = '' |
|
|
|
let dependencyContent = '' |
|
|
|
let path = include |
|
|
|
let path = include |
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
@ -268,20 +264,43 @@ export class CircomPluginClient extends PluginClient { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// extract all includes from the dependency content
|
|
|
|
const fileNameToInclude = extractNameFromKey(include) |
|
|
|
const dependencyIncludes = (dependencyContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
|
|
|
const similarFile = Object.keys(output).find(path => { |
|
|
|
|
|
|
|
return path.indexOf(fileNameToInclude) > -1 |
|
|
|
blackPath.push(include) |
|
|
|
}) |
|
|
|
// recursively resolve all dependencies of the dependency
|
|
|
|
const isDuplicateContent = similarFile && output[similarFile] ? output[similarFile].content === dependencyContent : false |
|
|
|
if (dependencyIncludes.length > 0) { |
|
|
|
|
|
|
|
await this.resolveDependencies(filePath, dependencyContent, output, path, blackPath) |
|
|
|
if (output[include] && output[include].parent) { |
|
|
|
output[include] = dependencyContent |
|
|
|
// if include import already exists, remove the include import from the parent file
|
|
|
|
|
|
|
|
const regexPattern = new RegExp(`include ['"]${include}['"];`, 'g') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output[output[include].parent].content = output[output[include].parent].content.replace(regexPattern, "") |
|
|
|
|
|
|
|
} else if (isDuplicateContent) { |
|
|
|
|
|
|
|
// if include import has the same content as another file, replace the include import with the file name of the other file (similarFile)
|
|
|
|
|
|
|
|
if (output[similarFile].parent) output[output[similarFile].parent].content = output[output[similarFile].parent].content.replace(similarFile, include) |
|
|
|
|
|
|
|
if (include !== similarFile) { |
|
|
|
|
|
|
|
output[include] = output[similarFile] |
|
|
|
|
|
|
|
delete output[similarFile] |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
output[include] = dependencyContent |
|
|
|
// extract all includes from the dependency content
|
|
|
|
|
|
|
|
const dependencyIncludes = (dependencyContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output[include] = { |
|
|
|
|
|
|
|
content: dependencyContent, |
|
|
|
|
|
|
|
parent |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// recursively resolve all dependencies of the dependency
|
|
|
|
|
|
|
|
if (dependencyIncludes.length > 0) await this.resolveDependencies(filePath, dependencyContent, output, path, include) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
) |
|
|
|
) |
|
|
|
return output |
|
|
|
const result: Record<string, string> = {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object.keys(output).forEach((key) => { |
|
|
|
|
|
|
|
result[key] = output[key].content |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
return result |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async resolveReportPath (path: string): Promise<string> { |
|
|
|
async resolveReportPath (path: string): Promise<string> { |
|
|
|