Implement sol-compiler offline mode

This commit is contained in:
Leonid Logvinov
2019-02-19 10:35:52 -08:00
parent 1c76f9a0ff
commit 1a3fd0227d
6 changed files with 85 additions and 6 deletions

View File

@@ -510,6 +510,7 @@ export interface Source {
* contracts: List of contract names you wish to compile, or alternatively ['*'] to compile all contracts in the
* specified directory.
* useDockerisedSolc: If set to true - sol-compiler will try calling a dockerized installations of solc to achieve faster compilation times. Otherwise and by default - solcjs will be used. Defaults to false.
* isOfflineMode: If set to true - sol-compiler will not fetch the list of solc releases from github. It will use the hardcoded list. Defaults to false.
* solcVersion: If you don't want to compile each contract with the Solidity version specified in-file, you can force all
* contracts to compile with the the version specified here.
*/
@@ -519,5 +520,6 @@ export interface CompilerOptions {
compilerSettings?: CompilerSettings;
contracts?: string[] | '*';
useDockerisedSolc?: boolean;
isOfflineMode?: boolean;
solcVersion?: string;
} // tslint:disable-line:max-file-line-count

View File

@@ -1,4 +1,13 @@
[
{
"version": "3.1.0",
"changes": [
{
"note": "Add `isOfflineMode` flag to sol-compiler`",
"pr": "TODO"
}
]
},
{
"timestamp": 1549733923,
"version": "3.0.3",

View File

@@ -45,6 +45,7 @@ const ALL_FILES_IDENTIFIER = '*';
const DEFAULT_CONTRACTS_DIR = path.resolve('contracts');
const DEFAULT_ARTIFACTS_DIR = path.resolve('artifacts');
const DEFAULT_USE_DOCKERISED_SOLC = false;
const DEFAULT_IS_OFFLINE_MODE = false;
// Solc compiler settings cannot be configured from the commandline.
// If you need this configured, please create a `compiler.json` config file
// with your desired configurations.
@@ -90,6 +91,7 @@ export class Compiler {
private readonly _solcVersionIfExists: string | undefined;
private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER;
private readonly _useDockerisedSolc: boolean;
private readonly _isOfflineMode: boolean;
/**
* Instantiates a new instance of the Compiler class.
* @param opts Optional compiler options
@@ -110,6 +112,7 @@ export class Compiler {
this._specifiedContracts = passedOpts.contracts || config.contracts || ALL_CONTRACTS_IDENTIFIER;
this._useDockerisedSolc =
passedOpts.useDockerisedSolc || config.useDockerisedSolc || DEFAULT_USE_DOCKERISED_SOLC;
this._isOfflineMode = passedOpts.isOfflineMode || config.isOfflineMode || DEFAULT_IS_OFFLINE_MODE;
this._nameResolver = new NameResolver(this._contractsDir);
const resolver = new FallthroughResolver();
resolver.appendResolver(new URLResolver());
@@ -211,7 +214,7 @@ export class Compiler {
// map contract paths to data about them for later verification and persistence
const contractPathToData: ContractPathToData = {};
const solcJSReleases = await getSolcJSReleasesAsync();
const solcJSReleases = await getSolcJSReleasesAsync(this._isOfflineMode);
const resolvedContractSources = [];
for (const contractName of contractNames) {
const spyResolver = new SpyResolver(this._resolver);
@@ -229,6 +232,13 @@ export class Compiler {
const solcVersion = _.isUndefined(this._solcVersionIfExists)
? semver.maxSatisfying(_.keys(solcJSReleases), parseSolidityVersionRange(contractSource.source))
: this._solcVersionIfExists;
if (_.isNull(solcVersion)) {
throw new Error(
`Couldn't find any solidity version satisfying the constraint ${parseSolidityVersionRange(
contractSource.source,
)}`,
);
}
const isFirstContractWithThisVersion = _.isUndefined(versionToInputs[solcVersion]);
if (isFirstContractWithThisVersion) {
versionToInputs[solcVersion] = {
@@ -274,7 +284,7 @@ export class Compiler {
compilerOutput = await compileDockerAsync(solcVersion, input.standardInput);
} else {
fullSolcVersion = solcJSReleases[solcVersion];
compilerOutput = await compileSolcJSAsync(solcVersion, input.standardInput);
compilerOutput = await compileSolcJSAsync(solcVersion, input.standardInput, this._isOfflineMode);
}
if (!_.isUndefined(compilerOutput.errors)) {
printCompilationErrorsAndWarnings(compilerOutput.errors);

View File

@@ -20,6 +20,7 @@ export const compilerOptionsSchema = {
],
},
useDockerisedSolc: { type: 'boolean' },
isOfflineMode: { type: 'boolean' },
},
type: 'object',
required: [],

View File

@@ -121,8 +121,12 @@ let solcJSReleasesCache: BinaryPaths | undefined;
/**
* Fetches the list of available solidity compilers
* @param isOfflineMode Offline mode flag
*/
export async function getSolcJSReleasesAsync(): Promise<BinaryPaths> {
export async function getSolcJSReleasesAsync(isOfflineMode: boolean): Promise<BinaryPaths> {
if (isOfflineMode) {
return constants.SOLC_BIN_PATHS;
}
if (_.isUndefined(solcJSReleasesCache)) {
const versionList = await fetch('https://ethereum.github.io/solc-bin/bin/list.json');
const versionListJSON = await versionList.json();
@@ -135,12 +139,14 @@ export async function getSolcJSReleasesAsync(): Promise<BinaryPaths> {
* Compiles the contracts and prints errors/warnings
* @param solcVersion Version of a solc compiler
* @param standardInput Solidity standard JSON input
* @param isOfflineMode Offline mode flag
*/
export async function compileSolcJSAsync(
solcVersion: string,
standardInput: solc.StandardInput,
isOfflineMode: boolean,
): Promise<solc.StandardOutput> {
const solcInstance = await getSolcJSAsync(solcVersion);
const solcInstance = await getSolcJSAsync(solcVersion, isOfflineMode);
const standardInputStr = JSON.stringify(standardInput);
const standardOutputStr = solcInstance.compileStandardWrapper(standardInputStr);
const compiled: solc.StandardOutput = JSON.parse(standardOutputStr);
@@ -329,9 +335,10 @@ function recursivelyGatherDependencySources(
* Gets the solidity compiler instance. If the compiler is already cached - gets it from FS,
* otherwise - fetches it and caches it.
* @param solcVersion The compiler version. e.g. 0.5.0
* @param isOfflineMode Offline mode flag
*/
export async function getSolcJSAsync(solcVersion: string): Promise<solc.SolcInstance> {
const solcJSReleases = await getSolcJSReleasesAsync();
export async function getSolcJSAsync(solcVersion: string, isOfflineMode: boolean): Promise<solc.SolcInstance> {
const solcJSReleases = await getSolcJSReleasesAsync(isOfflineMode);
const fullSolcVersion = solcJSReleases[solcVersion];
if (_.isUndefined(fullSolcVersion)) {
throw new Error(`${solcVersion} is not a known compiler version`);

View File

@@ -5,4 +5,54 @@ export const constants = {
BASE_COMPILER_URL: 'https://ethereum.github.io/solc-bin/bin/',
LATEST_ARTIFACT_VERSION: '2.0.0',
SOLC_BIN_DIR: path.join(__dirname, '..', '..', 'solc_bin'),
SOLC_BIN_PATHS: {
'0.5.4': 'soljson-v0.5.4+commit.9549d8ff.js',
'0.5.3': 'soljson-v0.5.3+commit.10d17f24.js',
'0.5.2': 'soljson-v0.5.2+commit.1df8f40c.js',
'0.5.1': 'soljson-v0.5.1+commit.c8a2cb62.js',
'0.5.0': 'soljson-v0.5.0+commit.1d4f565a.js',
'0.4.25': 'soljson-v0.4.25+commit.59dbf8f1.js',
'0.4.24': 'soljson-v0.4.24+commit.e67f0147.js',
'0.4.23': 'soljson-v0.4.23+commit.124ca40d.js',
'0.4.22': 'soljson-v0.4.22+commit.4cb486ee.js',
'0.4.21': 'soljson-v0.4.21+commit.dfe3193c.js',
'0.4.20': 'soljson-v0.4.20+commit.3155dd80.js',
'0.4.19': 'soljson-v0.4.19+commit.c4cbbb05.js',
'0.4.18': 'soljson-v0.4.18+commit.9cf6e910.js',
'0.4.17': 'soljson-v0.4.17+commit.bdeb9e52.js',
'0.4.16': 'soljson-v0.4.16+commit.d7661dd9.js',
'0.4.15': 'soljson-v0.4.15+commit.bbb8e64f.js',
'0.4.14': 'soljson-v0.4.14+commit.c2215d46.js',
'0.4.13': 'soljson-v0.4.13+commit.fb4cb1a.js',
'0.4.12': 'soljson-v0.4.12+commit.194ff033.js',
'0.4.11': 'soljson-v0.4.11+commit.68ef5810.js',
'0.4.10': 'soljson-v0.4.10+commit.f0d539ae.js',
'0.4.9': 'soljson-v0.4.9+commit.364da425.js',
'0.4.8': 'soljson-v0.4.8+commit.60cc1668.js',
'0.4.7': 'soljson-v0.4.7+commit.822622cf.js',
'0.4.6': 'soljson-v0.4.6+commit.2dabbdf0.js',
'0.4.5': 'soljson-v0.4.5+commit.b318366e.js',
'0.4.4': 'soljson-v0.4.4+commit.4633f3de.js',
'0.4.3': 'soljson-v0.4.3+commit.2353da71.js',
'0.4.2': 'soljson-v0.4.2+commit.af6afb04.js',
'0.4.1': 'soljson-v0.4.1+commit.4fc6fc2c.js',
'0.4.0': 'soljson-v0.4.0+commit.acd334c9.js',
'0.3.6': 'soljson-v0.3.6+commit.3fc68da.js',
'0.3.5': 'soljson-v0.3.5+commit.5f97274.js',
'0.3.4': 'soljson-v0.3.4+commit.7dab890.js',
'0.3.3': 'soljson-v0.3.3+commit.4dc1cb1.js',
'0.3.2': 'soljson-v0.3.2+commit.81ae2a7.js',
'0.3.1': 'soljson-v0.3.1+commit.c492d9b.js',
'0.3.0': 'soljson-v0.3.0+commit.11d6736.js',
'0.2.2': 'soljson-v0.2.2+commit.ef92f56.js',
'0.2.1': 'soljson-v0.2.1+commit.91a6b35.js',
'0.2.0': 'soljson-v0.2.0+commit.4dc2445.js',
'0.1.7': 'soljson-v0.1.7+commit.b4e666c.js',
'0.1.6': 'soljson-v0.1.6+commit.d41f8b7.js',
'0.1.5': 'soljson-v0.1.5+commit.23865e3.js',
'0.1.4': 'soljson-v0.1.4+commit.5f6c3cd.js',
'0.1.3': 'soljson-v0.1.3+commit.28f561.js',
'0.1.2': 'soljson-v0.1.2+commit.d0d36e3.js',
'0.1.1': 'soljson-v0.1.1+commit.6ff4cd6.js',
},
};