Skip to content

Commit

Permalink
Add support for custom compilers in solc-typed-ast versions (#273)
Browse files Browse the repository at this point in the history
  • Loading branch information
cd1m0 authored Sep 16, 2024
1 parent e92fc59 commit aadcbb3
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 52 deletions.
3 changes: 2 additions & 1 deletion src/bin/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
FunctionDefinition,
FunctionVisibility,
InferType,
isCustom,
isExact,
LatestCompilerVersion,
PathOptions,
Expand Down Expand Up @@ -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.'
Expand Down
107 changes: 58 additions & 49 deletions src/compile/kinds/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -97,71 +97,80 @@ export async function getCompilerForVersion<T extends CompilerMapping>(
version: string,
kind: T[0]
): Promise<T[1] | undefined> {
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<ArrayBuffer>(
`${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<ArrayBuffer>(
`${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) {
Expand Down
15 changes: 14 additions & 1 deletion src/compile/version.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import semver from "semver";
import { assert } from "../misc";

const rx = {
comments: /\/\*[\s\S]*?\*\/|\/\/.*$/gm,
Expand All @@ -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 {
Expand All @@ -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[]
Expand Down
4 changes: 3 additions & 1 deletion src/types/infer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit aadcbb3

Please sign in to comment.