From a9c00453688e018b5036e753d7f6b92463f96568 Mon Sep 17 00:00:00 2001 From: Dimitar Bounov Date: Mon, 16 Sep 2024 13:11:11 -1000 Subject: [PATCH] Add support for custom compilers in solc-typed-ast versions --- src/bin/compile.ts | 3 +- src/compile/kinds/compiler.ts | 107 ++++++++++++++++++---------------- src/compile/version.ts | 15 ++++- src/types/infer.ts | 4 +- 4 files changed, 77 insertions(+), 52 deletions(-) diff --git a/src/bin/compile.ts b/src/bin/compile.ts index ea9c6d20..b126bb31 100644 --- a/src/bin/compile.ts +++ b/src/bin/compile.ts @@ -26,6 +26,7 @@ import { FunctionDefinition, FunctionVisibility, InferType, + isCustom, isExact, LatestCompilerVersion, PathOptions, @@ -193,7 +194,7 @@ function error(message: string): never { const compilerVersion: string = options.compilerVersion; - if (!(compilerVersion === "auto" || isExact(compilerVersion))) { + if (!(compilerVersion === "auto" || isExact(compilerVersion) || isCustom(compilerVersion))) { const message = [ `Invalid compiler version "${compilerVersion}".`, 'Possible values: "auto" or exact version string.' diff --git a/src/compile/kinds/compiler.ts b/src/compile/kinds/compiler.ts index 7353d4e7..9f327612 100644 --- a/src/compile/kinds/compiler.ts +++ b/src/compile/kinds/compiler.ts @@ -6,7 +6,7 @@ import path from "path"; import { CompilerKind, CompilerVersions } from ".."; import { assert } from "../../misc"; import { SolcInput } from "../input"; -import { isExact } from "../version"; +import { getCustomPath, isCustom, isExact } from "../version"; import { BINARIES_URL, CACHE_DIR, @@ -97,71 +97,80 @@ export async function getCompilerForVersion( version: string, kind: T[0] ): Promise { - assert( - isExact(version), - "Version string must contain exact SemVer-formatted version without any operators" - ); + let compilerLocalPath: string; - let prefix: string | undefined; - - if (kind === CompilerKind.Native) { - prefix = getCompilerPrefixForOs(); - } else if (kind === CompilerKind.WASM) { - prefix = "wasm"; + if (isCustom(version)) { + compilerLocalPath = getCustomPath(version); } else { - throw new Error(`Unsupported compiler kind "${kind}"`); - } + assert( + isExact(version), + "Version string must contain exact SemVer-formatted version without any operators" + ); - assert(CompilerVersions.includes(version), `Unsupported ${kind} compiler version ${version}`); + let prefix: string | undefined; - if (prefix === undefined) { - return undefined; - } + if (kind === CompilerKind.Native) { + prefix = getCompilerPrefixForOs(); + } else if (kind === CompilerKind.WASM) { + prefix = "wasm"; + } else { + throw new Error(`Unsupported compiler kind "${kind}"`); + } - const md = await getCompilerMDForPlatform(prefix, version); - const compilerFileName = md.releases[version]; + assert( + CompilerVersions.includes(version), + `Unsupported ${kind} compiler version ${version}` + ); - if (compilerFileName === undefined) { - return undefined; - } + if (prefix === undefined) { + return undefined; + } + + const md = await getCompilerMDForPlatform(prefix, version); + const compilerFileName = md.releases[version]; - const compilerLocalPath = getCompilerLocalPath(prefix, compilerFileName); + if (compilerFileName === undefined) { + return undefined; + } - if (!fse.existsSync(compilerLocalPath)) { - const build = md.builds.find((b) => b.version === version); + compilerLocalPath = getCompilerLocalPath(prefix, compilerFileName); - assert( - build !== undefined, - `Unable to find build metadata for ${prefix} compiler ${version} in "list.json"` - ); + if (!fse.existsSync(compilerLocalPath)) { + const build = md.builds.find((b) => b.version === version); - const response = await axios.get( - `${BINARIES_URL}/${prefix}/${compilerFileName}`, - { - responseType: "arraybuffer" - } - ); + assert( + build !== undefined, + `Unable to find build metadata for ${prefix} compiler ${version} in "list.json"` + ); + + const response = await axios.get( + `${BINARIES_URL}/${prefix}/${compilerFileName}`, + { + responseType: "arraybuffer" + } + ); - const buf = Buffer.from(response.data); + const buf = Buffer.from(response.data); - const hash = crypto.createHash("sha256"); + const hash = crypto.createHash("sha256"); - hash.update(buf); + hash.update(buf); - const digest = "0x" + hash.digest("hex"); + const digest = "0x" + hash.digest("hex"); - assert( - digest === build.sha256, - `Downloaded ${prefix} compiler ${version} hash ${digest} does not match hash ${build.sha256} from "list.json"` - ); + assert( + digest === build.sha256, + `Downloaded ${prefix} compiler ${version} hash ${digest} does not match hash ${build.sha256} from "list.json"` + ); - /** - * Native compilers are exeсutable files, so give them proper permissions. - * WASM compilers are loaded by NodeJS, so write them as readonly common files. - */ - const permissions = kind === CompilerKind.Native ? 0o555 : 0o444; + /** + * Native compilers are exeсutable files, so give them proper permissions. + * WASM compilers are loaded by NodeJS, so write them as readonly common files. + */ + const permissions = kind === CompilerKind.Native ? 0o555 : 0o444; - await fse.writeFile(compilerLocalPath, buf, { mode: permissions }); + await fse.writeFile(compilerLocalPath, buf, { mode: permissions }); + } } if (kind === CompilerKind.Native) { diff --git a/src/compile/version.ts b/src/compile/version.ts index f86fb77f..5ce15117 100644 --- a/src/compile/version.ts +++ b/src/compile/version.ts @@ -1,4 +1,5 @@ import semver from "semver"; +import { assert } from "../misc"; const rx = { comments: /\/\*[\s\S]*?\*\/|\/\/.*$/gm, @@ -9,7 +10,8 @@ const rx = { spaceDash: /( -)/g, fixed: /^=?\d+\.\d+\.\d+$/, - exact: /^\d+.\d+.\d+$/ + exact: /^\d+.\d+.\d+$/, + custom: /^custom:(.*)/ }; export function isFixed(version: string): boolean { @@ -24,6 +26,17 @@ export function isExact(version: string): boolean { return rx.exact.test(version); } +export function isCustom(version: string): boolean { + return rx.custom.test(version); +} + +export function getCustomPath(version: string): string { + const m = version.match(rx.custom); + assert(m !== null, `Bad custom version {0}`, version); + + return m[1]; +} + export function getCompilerVersionsBySpecifiers( specifiers: string[], versions: string[] diff --git a/src/types/infer.ts b/src/types/infer.ts index 58a36450..06c380ce 100644 --- a/src/types/infer.ts +++ b/src/types/infer.ts @@ -2284,7 +2284,9 @@ export class InferType { return new UserDefinedType(getFQDefName(def), def); } - throw new Error(`NYI converting user-defined AST type ${def.print()} to TypeNode`); + throw new Error( + `NYI converting user-defined AST type ${def != undefined ? def.print() : undefined} to TypeNode` + ); } if (node instanceof FunctionTypeName) {