Skip to content

Commit

Permalink
Use Workers for earlier compilers
Browse files Browse the repository at this point in the history
  • Loading branch information
kuzdogan committed Aug 5, 2023
1 parent 4950365 commit da9e46d
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 4 deletions.
13 changes: 13 additions & 0 deletions packages/lib-sourcify/src/lib/compilerWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { workerData, parentPort } from 'worker_threads';
import { getSolcJs } from './solidityCompiler';

async function runUseCompiler(version: string, inputStringified: string) {
const solJson = await getSolcJs(version);
const result = solJson.compile(inputStringified);
if (parentPort === null) {
throw new Error('Parent port is null; cannot send compilation result');
}
parentPort.postMessage(result);
}

runUseCompiler(workerData.version, workerData.inputStringified);
40 changes: 37 additions & 3 deletions packages/lib-sourcify/src/lib/solidityCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { fetchWithTimeout } from './utils';
import { StatusCodes } from 'http-status-codes';
import { JsonInput, PathBuffer } from './types';
import { logDebug, logError, logInfo, logWarn } from './logger';
import semver from 'semver';
import { Worker, WorkerOptions } from 'worker_threads';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const solc = require('solc');

Expand Down Expand Up @@ -76,11 +78,31 @@ export async function useCompiler(version: string, solcJsonInput: JsonInput) {
}
compiled = shellOutputBuffer.stdout.toString();
} else {
const soljson = await getSolcJs(version);
const solJson = await getSolcJs(version);
startCompilation = Date.now();
logDebug(`Compiling with solc-js ${version}`);
if (soljson) {
compiled = soljson.compile(inputStringified);
if (solJson) {
const coercedVersion =
semver.coerce(new semver.SemVer(version))?.version ?? '';
// Run Worker for solc versions < 0.4.0 for clean compiler context. See https://github.com/ethereum/sourcify/issues/1099
if (semver.lt(coercedVersion, '0.4.0')) {
compiled = await new Promise((resolve, reject) => {
let worker = importWorker(
path.resolve(__dirname, './compilerWorker.ts'),
{
workerData: { version, inputStringified },
}
);
worker.once('message', (result) => {
resolve(result);
});
worker.once('error', (error) => {
reject(error);
});
});
} else {
compiled = solJson.compile(inputStringified);
}
}
}

Expand Down Expand Up @@ -112,6 +134,7 @@ export async function getAllMetadataAndSourcesFromSolcJson(
throw new Error(
'Only Solidity is supported, the json has language: ' + solcJson.language
);

const outputSelection = {
'*': {
'*': ['metadata'],
Expand Down Expand Up @@ -278,3 +301,14 @@ export async function getSolcJs(version = 'latest'): Promise<any> {
const solcjsImports = await import(soljsonPath);
return solc.setupMethods(solcjsImports);
}

// https://stackoverflow.com/questions/71795469/ts-node-using-worker-thread-cause-cannot-use-import-statement-outside-a-module
function importWorker(path: string, options: WorkerOptions) {
const resolvedPath = require.resolve(path);
return new Worker(resolvedPath, {
...options,
execArgv: /\.ts$/.test(resolvedPath)
? ['--require', 'ts-node/register']
: undefined,
});
}
21 changes: 20 additions & 1 deletion packages/lib-sourcify/test/functions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import storageMetadata from './sources/Storage/metadata.json';
import { Metadata, MissingSources } from '../src/lib/types';
import WrongMetadata from './sources/WrongMetadata/metadata.json';
import SimplyLog from './sources/WrongMetadata/SimplyLog.json';

import earlyCompilerInput from './sources/json-input/pre-v0.4.0/input.json';
import { keccak256 } from 'ethers';
describe('Verify Solidity Compiler', () => {
it('Should fetch latest SolcJS compiler', async () => {
expect(await getSolcJs()).not.equals(null);
Expand Down Expand Up @@ -111,6 +112,24 @@ describe('Verify Solidity Compiler', () => {
});
}
});

// See https://github.com/ethereum/sourcify/issues/1099
it(`Should should use a clean compiler context with pre 0.4.0 versions`, async () => {
// Run compiler once to change compiler "context"
await useCompiler('0.1.5+commit.23865e3', earlyCompilerInput);

// A second run needs to produce the same result
const compilerResult = await useCompiler(
'0.1.5+commit.23865e3',
earlyCompilerInput
);
const compiledBytecode = compilerResult.contracts[''].GroveLib.evm
.deployedBytecode.object as string;
const compiledHash = keccak256('0x' + compiledBytecode);
expect(compiledHash).equals(
'0xc778f3d42ce4a7ee21a2e93d45265cf771e5970e0e36f882310f4491d0ca889d'
);
});
});

describe('Checked contract', () => {
Expand Down

Large diffs are not rendered by default.

0 comments on commit da9e46d

Please sign in to comment.