From f42119c9286ad70504b6f8395bcdd801a1ac52c3 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 3 Aug 2018 22:36:32 +0200 Subject: Add missing compiler comments --- packages/sol-compiler/src/compiler.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3620a3ec1..2503f7315 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -67,6 +67,7 @@ export class Compiler { private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; /** * Instantiates a new instance of the Compiler class. + * @param opts Optional compiler options * @return An instance of the Compiler class. */ constructor(opts?: CompilerOptions) { -- cgit v1.2.3 From d89934954d22e5175a7d97f407e2cd43a04d0b57 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 22:31:04 -0700 Subject: extract function getSolcAsync() --- packages/sol-compiler/src/compiler.ts | 43 ++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3620a3ec1..5c99e3dae 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -53,6 +53,30 @@ const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { }; const CONFIG_FILE = 'compiler.json'; +async function getSolcAsync( + solcVersion: string, +): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + const fullSolcVersion = binPaths[solcVersion]; + const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); + let solcjs: string; + const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); + if (isCompilerAvailableLocally) { + solcjs = fs.readFileSync(compilerBinFilename).toString(); + } else { + logUtils.log(`Downloading ${fullSolcVersion}...`); + const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; + const response = await fetchAsync(url); + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { + throw new Error(`Failed to load ${fullSolcVersion}`); + } + solcjs = await response.text(); + fs.writeFileSync(compilerBinFilename, solcjs); + } + const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + return { solcInstance, fullSolcVersion }; +} + /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. @@ -139,24 +163,7 @@ export class Compiler { const availableCompilerVersions = _.keys(binPaths); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); } - const fullSolcVersion = binPaths[solcVersion]; - const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); - let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); - } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); - const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; - const response = await fetchAsync(url); - const SUCCESS_STATUS = 200; - if (response.status !== SUCCESS_STATUS) { - throw new Error(`Failed to load ${fullSolcVersion}`); - } - solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); - } - const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); const standardInput: solc.StandardInput = { -- cgit v1.2.3 From 478bf14289d1555753353b837e4efc63b2c776fe Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 22:48:14 -0700 Subject: extract method _compile() --- packages/sol-compiler/src/compiler.ts | 51 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 5c99e3dae..83caa2a19 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -175,30 +175,7 @@ export class Compiler { }, settings: this._compilerSettings, }; - const compiled: solc.StandardOutput = JSON.parse( - solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { - const sourceCodeIfExists = this._resolver.resolve(importPath); - return { contents: sourceCodeIfExists.source }; - }), - ); - - if (!_.isUndefined(compiled.errors)) { - const SOLIDITY_WARNING = 'warning'; - const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING); - const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING); - if (!_.isEmpty(errors)) { - errors.forEach(error => { - const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); - logUtils.log(chalk.red(normalizedErrMsg)); - }); - process.exit(1); - } else { - warnings.forEach(warning => { - const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); - logUtils.log(chalk.yellow(normalizedWarningMsg)); - }); - } - } + const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); const compiledData = compiled.contracts[contractSource.path][contractName]; if (_.isUndefined(compiledData)) { throw new Error( @@ -258,6 +235,32 @@ export class Compiler { await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); logUtils.log(`${contractName} artifact saved!`); } + private _compile(solcInstance: solc.SolcInstance, standardInput: solc.StandardInput): solc.StandardOutput { + const compiled: solc.StandardOutput = JSON.parse( + solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { + const sourceCodeIfExists = this._resolver.resolve(importPath); + return { contents: sourceCodeIfExists.source }; + }), + ); + if (!_.isUndefined(compiled.errors)) { + const SOLIDITY_WARNING = 'warning'; + const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING); + const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING); + if (!_.isEmpty(errors)) { + errors.forEach(error => { + const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); + logUtils.log(chalk.red(normalizedErrMsg)); + }); + throw new Error("Compilation errors encountered"); + } else { + warnings.forEach(warning => { + const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); + logUtils.log(chalk.yellow(normalizedWarningMsg)); + }); + } + } + return compiled; + } /** * Gets the source tree hash for a file and its dependencies. * @param fileName Name of contract file. -- cgit v1.2.3 From 783bc873db04a9f712300e57a346ce803b85590c Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 23:09:07 -0700 Subject: extract method _verifyAndPersistCompilationAsync() --- packages/sol-compiler/src/compiler.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 83caa2a19..f301b697b 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -176,6 +176,23 @@ export class Compiler { settings: this._compilerSettings, }; const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); + return this._verifyAndPersistCompilationAsync( + contractSource, + contractName, + fullSolcVersion, + compiled, + sourceTreeHashHex, + currentArtifactIfExists, + ); + } + private async _verifyAndPersistCompilationAsync( + contractSource: { path: string }, + contractName: string, + fullSolcVersion: string, + compiled: solc.StandardOutput, + sourceTreeHashHex: string, + currentArtifactIfExists: ContractArtifact | void, + ): Promise { const compiledData = compiled.contracts[contractSource.path][contractName]; if (_.isUndefined(compiledData)) { throw new Error( @@ -251,7 +268,7 @@ export class Compiler { const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); logUtils.log(chalk.red(normalizedErrMsg)); }); - throw new Error("Compilation errors encountered"); + throw new Error('Compilation errors encountered'); } else { warnings.forEach(warning => { const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); -- cgit v1.2.3 From 014d71d5ae4e6ec2f4841b5153d2116d3bbf25a6 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 23:27:52 -0700 Subject: compile contracts in batches one batch per compiler version needed. --- packages/sol-compiler/src/compiler.ts | 101 +++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 31 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index f301b697b..63154f917 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -131,31 +131,50 @@ export class Compiler { } else { contractNamesToCompile = this._specifiedContracts; } - for (const contractNameToCompile of contractNamesToCompile) { - await this._compileContractAsync(contractNameToCompile); - } + return this._compileContractsAsync(contractNamesToCompile); } /** * Compiles contract and saves artifact to artifactsDir. * @param fileName Name of contract with '.sol' extension. */ - private async _compileContractAsync(contractName: string): Promise { + private async _compileContractsAsync(contractNames: string[]): Promise { + const inputsByVersion: { + [solcVersion: string]: { + standardInput: solc.StandardInput; + contractsToCompile: string[]; + }; + } = {}; + + const contractData: { + [contractPath: string]: { + currentArtifactIfExists: ContractArtifact | void; + sourceTreeHashHex: string; + contractName: string; + }; + } = {}; + + for (const contractName of contractNames) { const contractSource = this._resolver.resolve(contractName); - const absoluteContractPath = path.join(this._contractsDir, contractSource.path); - const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName); - const sourceTreeHashHex = `0x${this._getSourceTreeHash(absoluteContractPath).toString('hex')}`; + contractData[contractSource.path] = { + contractName, + currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), + sourceTreeHashHex: `0x${this._getSourceTreeHash( + path.join(this._contractsDir, contractSource.path), + ).toString('hex')}`, + }; let shouldCompile = false; - if (_.isUndefined(currentArtifactIfExists)) { + if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { shouldCompile = true; } else { - const currentArtifact = currentArtifactIfExists as ContractArtifact; + const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); - const didSourceChange = currentArtifact.sourceTreeHashHex !== sourceTreeHashHex; + const didSourceChange = + currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } if (!shouldCompile) { - return; + continue; } let solcVersion = this._solcVersionIfExists; if (_.isUndefined(solcVersion)) { @@ -163,27 +182,47 @@ export class Compiler { const availableCompilerVersions = _.keys(binPaths); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); } - const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); - - logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); - const standardInput: solc.StandardInput = { - language: 'Solidity', - sources: { - [contractSource.path]: { - content: contractSource.source, + if (_.isUndefined(inputsByVersion[solcVersion])) { + inputsByVersion[solcVersion] = { + standardInput: { + language: 'Solidity', + sources: {}, + settings: this._compilerSettings, }, - }, - settings: this._compilerSettings, - }; - const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); - return this._verifyAndPersistCompilationAsync( - contractSource, - contractName, - fullSolcVersion, - compiled, - sourceTreeHashHex, - currentArtifactIfExists, - ); + contractsToCompile: [], + }; + } + inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source }; + inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); + } + + for (const solcVersion in inputsByVersion) { + if (!inputsByVersion.hasOwnProperty(solcVersion)) { + continue; + } + + const input = inputsByVersion[solcVersion]; + logUtils.log( + `Compiling ${input.contractsToCompile.length} contracts (${ + input.contractsToCompile + }) with Solidity v${solcVersion}...`, + ); + + const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); + + const compiled = this._compile(solcInstance, input.standardInput); + + for (const contractPath of input.contractsToCompile) { + await this._verifyAndPersistCompilationAsync( + { path: contractPath }, + contractData[contractPath].contractName, + fullSolcVersion, + compiled, + contractData[contractPath].sourceTreeHashHex, + contractData[contractPath].currentArtifactIfExists, + ); + } + } } private async _verifyAndPersistCompilationAsync( contractSource: { path: string }, -- cgit v1.2.3 From db6de490b21b6df8dd414c58657c3b48c39dd6d0 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 13 Aug 2018 23:59:00 -0700 Subject: corrected whitespace (no functional changes) --- packages/sol-compiler/src/compiler.ts | 80 ++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 39 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 63154f917..897ace9b6 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -154,46 +154,48 @@ export class Compiler { } = {}; for (const contractName of contractNames) { - const contractSource = this._resolver.resolve(contractName); - contractData[contractSource.path] = { - contractName, - currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), - sourceTreeHashHex: `0x${this._getSourceTreeHash( - path.join(this._contractsDir, contractSource.path), - ).toString('hex')}`, - }; - let shouldCompile = false; - if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { - shouldCompile = true; - } else { - const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; - const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; - const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); - const didSourceChange = - currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; - shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; - } - if (!shouldCompile) { - continue; - } - let solcVersion = this._solcVersionIfExists; - if (_.isUndefined(solcVersion)) { - const solcVersionRange = parseSolidityVersionRange(contractSource.source); - const availableCompilerVersions = _.keys(binPaths); - solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); - } - if (_.isUndefined(inputsByVersion[solcVersion])) { - inputsByVersion[solcVersion] = { - standardInput: { - language: 'Solidity', - sources: {}, - settings: this._compilerSettings, - }, - contractsToCompile: [], + const contractSource = this._resolver.resolve(contractName); + contractData[contractSource.path] = { + contractName, + currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), + sourceTreeHashHex: `0x${this._getSourceTreeHash( + path.join(this._contractsDir, contractSource.path), + ).toString('hex')}`, }; - } - inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source }; - inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); + let shouldCompile = false; + if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { + shouldCompile = true; + } else { + const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; + const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; + const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); + const didSourceChange = + currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; + shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; + } + if (!shouldCompile) { + continue; + } + let solcVersion = this._solcVersionIfExists; + if (_.isUndefined(solcVersion)) { + const solcVersionRange = parseSolidityVersionRange(contractSource.source); + const availableCompilerVersions = _.keys(binPaths); + solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); + } + if (_.isUndefined(inputsByVersion[solcVersion])) { + inputsByVersion[solcVersion] = { + standardInput: { + language: 'Solidity', + sources: {}, + settings: this._compilerSettings, + }, + contractsToCompile: [], + }; + } + inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { + content: contractSource.source, + }; + inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); } for (const solcVersion in inputsByVersion) { -- cgit v1.2.3 From aa27346f93fafa5fdc9fca69c5604caca9278dfd Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 14 Aug 2018 10:43:31 -0700 Subject: simplify method parameter --- packages/sol-compiler/src/compiler.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 897ace9b6..3b46d7b46 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -216,7 +216,7 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompilationAsync( - { path: contractPath }, + contractPath, contractData[contractPath].contractName, fullSolcVersion, compiled, @@ -227,19 +227,17 @@ export class Compiler { } } private async _verifyAndPersistCompilationAsync( - contractSource: { path: string }, + contractPath: string, contractName: string, fullSolcVersion: string, compiled: solc.StandardOutput, sourceTreeHashHex: string, currentArtifactIfExists: ContractArtifact | void, ): Promise { - const compiledData = compiled.contracts[contractSource.path][contractName]; + const compiledData = compiled.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( - `Contract ${contractName} not found in ${ - contractSource.path - }. Please make sure your contract has the same name as it's file name`, + `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, ); } if (!_.isUndefined(compiledData.evm)) { -- cgit v1.2.3 From e79c7632e6e82ecc53563da6d8727ce4475078c6 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 14 Aug 2018 10:52:31 -0700 Subject: simplify method interface --- packages/sol-compiler/src/compiler.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3b46d7b46..cf12825c4 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -215,25 +215,29 @@ export class Compiler { const compiled = this._compile(solcInstance, input.standardInput); for (const contractPath of input.contractsToCompile) { - await this._verifyAndPersistCompilationAsync( + await this._verifyAndPersistCompiledContractAsync( contractPath, - contractData[contractPath].contractName, + contractData[contractPath], fullSolcVersion, compiled, - contractData[contractPath].sourceTreeHashHex, - contractData[contractPath].currentArtifactIfExists, ); } } } - private async _verifyAndPersistCompilationAsync( + private async _verifyAndPersistCompiledContractAsync( contractPath: string, - contractName: string, + contractMetadata: { + currentArtifactIfExists: ContractArtifact | void; + sourceTreeHashHex: string; + contractName: string; + }, fullSolcVersion: string, compiled: solc.StandardOutput, - sourceTreeHashHex: string, - currentArtifactIfExists: ContractArtifact | void, ): Promise { + const contractName = contractMetadata.contractName; + const sourceTreeHashHex = contractMetadata.sourceTreeHashHex; + const currentArtifactIfExists = contractMetadata.currentArtifactIfExists; + const compiledData = compiled.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( -- cgit v1.2.3 From c01810f0d755bdb3fa7b4b224a5a0d0493cd38a7 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:13:09 -0700 Subject: move getSolcAsync to static private method --- packages/sol-compiler/src/compiler.ts | 49 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index cf12825c4..c62a4c0ca 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -53,30 +53,6 @@ const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { }; const CONFIG_FILE = 'compiler.json'; -async function getSolcAsync( - solcVersion: string, -): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { - const fullSolcVersion = binPaths[solcVersion]; - const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); - let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); - } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); - const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; - const response = await fetchAsync(url); - const SUCCESS_STATUS = 200; - if (response.status !== SUCCESS_STATUS) { - throw new Error(`Failed to load ${fullSolcVersion}`); - } - solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); - } - const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); - return { solcInstance, fullSolcVersion }; -} - /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. @@ -210,7 +186,7 @@ export class Compiler { }) with Solidity v${solcVersion}...`, ); - const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); + const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion); const compiled = this._compile(solcInstance, input.standardInput); @@ -224,6 +200,29 @@ export class Compiler { } } } + private static async _getSolcAsync( + solcVersion: string, + ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + const fullSolcVersion = binPaths[solcVersion]; + const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); + let solcjs: string; + const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); + if (isCompilerAvailableLocally) { + solcjs = fs.readFileSync(compilerBinFilename).toString(); + } else { + logUtils.log(`Downloading ${fullSolcVersion}...`); + const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; + const response = await fetchAsync(url); + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { + throw new Error(`Failed to load ${fullSolcVersion}`); + } + solcjs = await response.text(); + fs.writeFileSync(compilerBinFilename, solcjs); + } + const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + return { solcInstance, fullSolcVersion }; + } private async _verifyAndPersistCompiledContractAsync( contractPath: string, contractMetadata: { -- cgit v1.2.3 From d744468479bf88c89412115860e0b8c4cf2a48c1 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:21:46 -0700 Subject: rename variable inputsByVersion to versionToInputs --- packages/sol-compiler/src/compiler.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index c62a4c0ca..0de8b8cad 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -114,7 +114,7 @@ export class Compiler { * @param fileName Name of contract with '.sol' extension. */ private async _compileContractsAsync(contractNames: string[]): Promise { - const inputsByVersion: { + const versionToInputs: { [solcVersion: string]: { standardInput: solc.StandardInput; contractsToCompile: string[]; @@ -158,8 +158,8 @@ export class Compiler { const availableCompilerVersions = _.keys(binPaths); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); } - if (_.isUndefined(inputsByVersion[solcVersion])) { - inputsByVersion[solcVersion] = { + if (_.isUndefined(versionToInputs[solcVersion])) { + versionToInputs[solcVersion] = { standardInput: { language: 'Solidity', sources: {}, @@ -168,18 +168,18 @@ export class Compiler { contractsToCompile: [], }; } - inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { + versionToInputs[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source, }; - inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path); + versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - for (const solcVersion in inputsByVersion) { - if (!inputsByVersion.hasOwnProperty(solcVersion)) { + for (const solcVersion in versionToInputs) { + if (!versionToInputs.hasOwnProperty(solcVersion)) { continue; } - const input = inputsByVersion[solcVersion]; + const input = versionToInputs[solcVersion]; logUtils.log( `Compiling ${input.contractsToCompile.length} contracts (${ input.contractsToCompile -- cgit v1.2.3 From f0f94f199eff982ffa03c6a760235ed22a8ad68a Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:13:09 -0700 Subject: move getSolcAsync to static private method --- packages/sol-compiler/src/compiler.ts | 46 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 0de8b8cad..c162d65f4 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -65,6 +65,29 @@ export class Compiler { private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; + private static async _getSolcAsync( + solcVersion: string, + ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + const fullSolcVersion = binPaths[solcVersion]; + const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); + let solcjs: string; + const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); + if (isCompilerAvailableLocally) { + solcjs = fs.readFileSync(compilerBinFilename).toString(); + } else { + logUtils.log(`Downloading ${fullSolcVersion}...`); + const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; + const response = await fetchAsync(url); + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { + throw new Error(`Failed to load ${fullSolcVersion}`); + } + solcjs = await response.text(); + fs.writeFileSync(compilerBinFilename, solcjs); + } + const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); + return { solcInstance, fullSolcVersion }; + } /** * Instantiates a new instance of the Compiler class. * @return An instance of the Compiler class. @@ -200,29 +223,6 @@ export class Compiler { } } } - private static async _getSolcAsync( - solcVersion: string, - ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { - const fullSolcVersion = binPaths[solcVersion]; - const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); - let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); - } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); - const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; - const response = await fetchAsync(url); - const SUCCESS_STATUS = 200; - if (response.status !== SUCCESS_STATUS) { - throw new Error(`Failed to load ${fullSolcVersion}`); - } - solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); - } - const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); - return { solcInstance, fullSolcVersion }; - } private async _verifyAndPersistCompiledContractAsync( contractPath: string, contractMetadata: { -- cgit v1.2.3 From 558286467bc7c05ea1a97a1fdfde0ad1ba7e279f Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:46:23 -0700 Subject: extract interfaces for re-used complex data types --- packages/sol-compiler/src/compiler.ts | 51 +++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index c162d65f4..286f15073 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -53,6 +53,23 @@ const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { }; const CONFIG_FILE = 'compiler.json'; +interface VersionToInputs { + [solcVersion: string]: { + standardInput: solc.StandardInput; + contractsToCompile: string[]; + }; +} + +interface ContractPathToData { + [contractPath: string]: ContractData; +} + +interface ContractData { + currentArtifactIfExists: ContractArtifact | void; + sourceTreeHashHex: string; + contractName: string; +} + /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. @@ -137,24 +154,15 @@ export class Compiler { * @param fileName Name of contract with '.sol' extension. */ private async _compileContractsAsync(contractNames: string[]): Promise { - const versionToInputs: { - [solcVersion: string]: { - standardInput: solc.StandardInput; - contractsToCompile: string[]; - }; - } = {}; + // batch input contracts together based on the version of the compiler that they require. + const versionToInputs: VersionToInputs = {}; - const contractData: { - [contractPath: string]: { - currentArtifactIfExists: ContractArtifact | void; - sourceTreeHashHex: string; - contractName: string; - }; - } = {}; + // map contract paths to data about them for later verification and persistence + const contractPathToData: ContractPathToData = {}; for (const contractName of contractNames) { const contractSource = this._resolver.resolve(contractName); - contractData[contractSource.path] = { + contractPathToData[contractSource.path] = { contractName, currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), sourceTreeHashHex: `0x${this._getSourceTreeHash( @@ -162,14 +170,15 @@ export class Compiler { ).toString('hex')}`, }; let shouldCompile = false; - if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) { + if (_.isUndefined(contractPathToData[contractSource.path].currentArtifactIfExists)) { shouldCompile = true; } else { - const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact; + const currentArtifact = contractPathToData[contractSource.path] + .currentArtifactIfExists as ContractArtifact; const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); const didSourceChange = - currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex; + currentArtifact.sourceTreeHashHex !== contractPathToData[contractSource.path].sourceTreeHashHex; shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } if (!shouldCompile) { @@ -216,7 +225,7 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompiledContractAsync( contractPath, - contractData[contractPath], + contractPathToData[contractPath], fullSolcVersion, compiled, ); @@ -225,11 +234,7 @@ export class Compiler { } private async _verifyAndPersistCompiledContractAsync( contractPath: string, - contractMetadata: { - currentArtifactIfExists: ContractArtifact | void; - sourceTreeHashHex: string; - contractName: string; - }, + contractMetadata: ContractData, fullSolcVersion: string, compiled: solc.StandardOutput, ): Promise { -- cgit v1.2.3 From ad9a7d72ced3898d7ba2922433bc666980f81b4e Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 11:58:10 -0700 Subject: remedy missing *IfExists identifier suffix --- packages/sol-compiler/src/compiler.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 286f15073..1c08cb324 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -184,12 +184,9 @@ export class Compiler { if (!shouldCompile) { continue; } - let solcVersion = this._solcVersionIfExists; - if (_.isUndefined(solcVersion)) { - const solcVersionRange = parseSolidityVersionRange(contractSource.source); - const availableCompilerVersions = _.keys(binPaths); - solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); - } + const solcVersion = _.isUndefined(this._solcVersionIfExists) + ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) + : this._solcVersionIfExists; if (_.isUndefined(versionToInputs[solcVersion])) { versionToInputs[solcVersion] = { standardInput: { -- cgit v1.2.3 From 7c96fa45f85906a9ba4d09b8aaa4759e7d55286f Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 12:50:20 -0700 Subject: comments --- packages/sol-compiler/src/compiler.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 1c08cb324..ff3805073 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -188,6 +188,8 @@ export class Compiler { ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) : this._solcVersionIfExists; if (_.isUndefined(versionToInputs[solcVersion])) { + // no inputs batched yet for this version. + // prepare object to hold this batch. versionToInputs[solcVersion] = { standardInput: { language: 'Solidity', @@ -197,6 +199,7 @@ export class Compiler { contractsToCompile: [], }; } + // add input to the right version batch versionToInputs[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source, }; -- cgit v1.2.3 From 8959b0993e92d86fdf8539d11d4e4c70185eb8ed Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 13:38:41 -0700 Subject: raise error for unknown compiler version --- packages/sol-compiler/src/compiler.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index ff3805073..9a6dcff09 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -85,6 +85,9 @@ export class Compiler { private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { + if (_.isUndefined(binPaths[solcVersion])) { + throw new Error(`${solcVersion} is not a known compiler version`); + } const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; -- cgit v1.2.3 From ec41e314b09ed348e1d268b1d896dbde275deb1b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 13:39:33 -0700 Subject: use `for...of _.keys` instead of `for...in` --- packages/sol-compiler/src/compiler.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 9a6dcff09..a676423cb 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -209,11 +209,7 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - for (const solcVersion in versionToInputs) { - if (!versionToInputs.hasOwnProperty(solcVersion)) { - continue; - } - + for (const solcVersion of _.keys(versionToInputs)) { const input = versionToInputs[solcVersion]; logUtils.log( `Compiling ${input.contractsToCompile.length} contracts (${ -- cgit v1.2.3 From 455c78dfb1ee5a104964b70d0132438b86f6c437 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 14:09:57 -0700 Subject: renamed variable `compiled` to `compilerOutput` --- packages/sol-compiler/src/compiler.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index a676423cb..f0cb2ded3 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -219,14 +219,14 @@ export class Compiler { const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion); - const compiled = this._compile(solcInstance, input.standardInput); + const compilerOutput = this._compile(solcInstance, input.standardInput); for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompiledContractAsync( contractPath, contractPathToData[contractPath], fullSolcVersion, - compiled, + compilerOutput, ); } } @@ -235,13 +235,13 @@ export class Compiler { contractPath: string, contractMetadata: ContractData, fullSolcVersion: string, - compiled: solc.StandardOutput, + compilerOutput: solc.StandardOutput, ): Promise { const contractName = contractMetadata.contractName; const sourceTreeHashHex = contractMetadata.sourceTreeHashHex; const currentArtifactIfExists = contractMetadata.currentArtifactIfExists; - const compiledData = compiled.contracts[contractPath][contractName]; + const compiledData = compilerOutput.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, @@ -262,12 +262,12 @@ export class Compiler { } const sourceCodes = _.mapValues( - compiled.sources, + compilerOutput.sources, (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, ); const contractVersion: ContractVersionData = { compilerOutput: compiledData, - sources: compiled.sources, + sources: compilerOutput.sources, sourceCodes, sourceTreeHashHex, compiler: { -- cgit v1.2.3 From badcb35525a4ccd5c80b7ad79288b267b961faef Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 15 Aug 2018 16:14:36 -0700 Subject: extract method _shouldCompile() --- packages/sol-compiler/src/compiler.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index f0cb2ded3..390c2412a 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -172,19 +172,7 @@ export class Compiler { path.join(this._contractsDir, contractSource.path), ).toString('hex')}`, }; - let shouldCompile = false; - if (_.isUndefined(contractPathToData[contractSource.path].currentArtifactIfExists)) { - shouldCompile = true; - } else { - const currentArtifact = contractPathToData[contractSource.path] - .currentArtifactIfExists as ContractArtifact; - const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; - const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); - const didSourceChange = - currentArtifact.sourceTreeHashHex !== contractPathToData[contractSource.path].sourceTreeHashHex; - shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; - } - if (!shouldCompile) { + if (!this._shouldCompile(contractPathToData[contractSource.path])) { continue; } const solcVersion = _.isUndefined(this._solcVersionIfExists) @@ -231,6 +219,17 @@ export class Compiler { } } } + private _shouldCompile(contractData: ContractData): boolean { + if (_.isUndefined(contractData.currentArtifactIfExists)) { + return true; + } else { + const currentArtifact = contractData.currentArtifactIfExists as ContractArtifact; + const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; + const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); + const didSourceChange = currentArtifact.sourceTreeHashHex !== contractData.sourceTreeHashHex; + return !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; + } + } private async _verifyAndPersistCompiledContractAsync( contractPath: string, contractMetadata: ContractData, -- cgit v1.2.3 From 6b6b368bf6b3d9c6f69d47a2f304919c7e1c6ae1 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:29:36 -0700 Subject: consolidate binPaths... ref's into fullSolcVersion --- packages/sol-compiler/src/compiler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 390c2412a..1af11dcd0 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -85,10 +85,10 @@ export class Compiler { private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { - if (_.isUndefined(binPaths[solcVersion])) { + const fullSolcVersion = binPaths[solcVersion]; + if (_.isUndefined(fullSolcVersion)) { throw new Error(`${solcVersion} is not a known compiler version`); } - const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); -- cgit v1.2.3 From 11231795cd73c24fe1d4e2d5ee826e46271b8a62 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:32:27 -0700 Subject: change `return Promise` to `await...` --- packages/sol-compiler/src/compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 1af11dcd0..eb9670b03 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -150,7 +150,7 @@ export class Compiler { } else { contractNamesToCompile = this._specifiedContracts; } - return this._compileContractsAsync(contractNamesToCompile); + await this._compileContractsAsync(contractNamesToCompile); } /** * Compiles contract and saves artifact to artifactsDir. -- cgit v1.2.3 From acb3c0d0aa065edf1c71970467d038d52096e865 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:36:12 -0700 Subject: declare contractData before adding to map --- packages/sol-compiler/src/compiler.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index eb9670b03..bd7f751df 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -165,16 +165,17 @@ export class Compiler { for (const contractName of contractNames) { const contractSource = this._resolver.resolve(contractName); - contractPathToData[contractSource.path] = { + const contractData = { contractName, currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName), sourceTreeHashHex: `0x${this._getSourceTreeHash( path.join(this._contractsDir, contractSource.path), ).toString('hex')}`, }; - if (!this._shouldCompile(contractPathToData[contractSource.path])) { + if (!this._shouldCompile(contractData)) { continue; } + contractPathToData[contractSource.path] = contractData; const solcVersion = _.isUndefined(this._solcVersionIfExists) ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) : this._solcVersionIfExists; -- cgit v1.2.3 From 421a7394dfcbc714b35ada8f8d8a9945b989d3c7 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:47:33 -0700 Subject: scrap comments in favor of self-documentation --- packages/sol-compiler/src/compiler.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index bd7f751df..713d8abe8 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -179,9 +179,8 @@ export class Compiler { const solcVersion = _.isUndefined(this._solcVersionIfExists) ? semver.maxSatisfying(_.keys(binPaths), parseSolidityVersionRange(contractSource.source)) : this._solcVersionIfExists; - if (_.isUndefined(versionToInputs[solcVersion])) { - // no inputs batched yet for this version. - // prepare object to hold this batch. + const isFirstContractWithThisVersion = _.isUndefined(versionToInputs[solcVersion]); + if (isFirstContractWithThisVersion) { versionToInputs[solcVersion] = { standardInput: { language: 'Solidity', -- cgit v1.2.3 From a607a61bde1677833a04765b8691184c49b04213 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:48:33 -0700 Subject: clarify iteration range --- packages/sol-compiler/src/compiler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 713d8abe8..bb870e0cf 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -197,7 +197,8 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - for (const solcVersion of _.keys(versionToInputs)) { + const solcVersions = _.keys(versionToInputs); + for (const solcVersion of solcVersions) { const input = versionToInputs[solcVersion]; logUtils.log( `Compiling ${input.contractsToCompile.length} contracts (${ -- cgit v1.2.3 From a59f18927dc8f59bb69d7dff9d0e5cd7e148129b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 10:57:31 -0700 Subject: flatten out interface to verifyAndPersist* method --- packages/sol-compiler/src/compiler.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index bb870e0cf..296411b76 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -213,7 +213,9 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { await this._verifyAndPersistCompiledContractAsync( contractPath, - contractPathToData[contractPath], + contractPathToData[contractPath].currentArtifactIfExists, + contractPathToData[contractPath].sourceTreeHashHex, + contractPathToData[contractPath].contractName, fullSolcVersion, compilerOutput, ); @@ -233,14 +235,12 @@ export class Compiler { } private async _verifyAndPersistCompiledContractAsync( contractPath: string, - contractMetadata: ContractData, + currentArtifactIfExists: ContractArtifact | void, + sourceTreeHashHex: string, + contractName: string, fullSolcVersion: string, compilerOutput: solc.StandardOutput, ): Promise { - const contractName = contractMetadata.contractName; - const sourceTreeHashHex = contractMetadata.sourceTreeHashHex; - const currentArtifactIfExists = contractMetadata.currentArtifactIfExists; - const compiledData = compilerOutput.contracts[contractPath][contractName]; if (_.isUndefined(compiledData)) { throw new Error( -- cgit v1.2.3 From 402ca27fbf91f543addf0d4618e071ae10cfd70e Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 13:59:46 -0700 Subject: change some *Sync to *Async --- packages/sol-compiler/src/compiler.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 296411b76..d3c4a3919 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -82,6 +82,18 @@ export class Compiler { private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; + private static async _doesFileExistAsync(filePath: string): Promise { + try { + await fsWrapper.accessAsync( + filePath, + // node says we need to use bitwise, but tslint says no: + fs.constants.F_OK | fs.constants.R_OK, // tslint:disable-line:no-bitwise + ); + } catch (err) { + return false; + } + return true; + } private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { @@ -91,9 +103,8 @@ export class Compiler { } const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; - const isCompilerAvailableLocally = fs.existsSync(compilerBinFilename); - if (isCompilerAvailableLocally) { - solcjs = fs.readFileSync(compilerBinFilename).toString(); + if (await Compiler._doesFileExistAsync(compilerBinFilename)) { + solcjs = (await fsWrapper.readFileAsync(compilerBinFilename)).toString(); } else { logUtils.log(`Downloading ${fullSolcVersion}...`); const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; @@ -103,7 +114,10 @@ export class Compiler { throw new Error(`Failed to load ${fullSolcVersion}`); } solcjs = await response.text(); - fs.writeFileSync(compilerBinFilename, solcjs); + await fsWrapper.writeFileAsync(compilerBinFilename, solcjs); + } + if (solcjs.length === 0) { + throw new Error('No compiler available'); } const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); return { solcInstance, fullSolcVersion }; -- cgit v1.2.3 From 445177bf420049041ade4d7526a5f4a8194bd216 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 16 Aug 2018 15:26:20 -0700 Subject: move doesFileExist to fsWrapper --- packages/sol-compiler/src/compiler.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index d3c4a3919..2e7120361 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -82,18 +82,6 @@ export class Compiler { private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; - private static async _doesFileExistAsync(filePath: string): Promise { - try { - await fsWrapper.accessAsync( - filePath, - // node says we need to use bitwise, but tslint says no: - fs.constants.F_OK | fs.constants.R_OK, // tslint:disable-line:no-bitwise - ); - } catch (err) { - return false; - } - return true; - } private static async _getSolcAsync( solcVersion: string, ): Promise<{ solcInstance: solc.SolcInstance; fullSolcVersion: string }> { @@ -103,7 +91,7 @@ export class Compiler { } const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; - if (await Compiler._doesFileExistAsync(compilerBinFilename)) { + if (await fsWrapper.doesFileExistAsync(compilerBinFilename)) { solcjs = (await fsWrapper.readFileAsync(compilerBinFilename)).toString(); } else { logUtils.log(`Downloading ${fullSolcVersion}...`); -- cgit v1.2.3 From 301cb296ec77e8af5c1722679e04cb983c848153 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Tue, 21 Aug 2018 23:58:06 +0100 Subject: Move types from sol-compiler to types so they can be used in other places without requiring sol-compiler as a dep --- packages/sol-compiler/src/compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 2503f7315..eb4ff3be6 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -10,6 +10,7 @@ import { } from '@0xproject/sol-resolver'; import { fetchAsync, logUtils } from '@0xproject/utils'; import chalk from 'chalk'; +import { CompilerOptions, ContractArtifact, ContractVersionData } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as fs from 'fs'; import * as _ from 'lodash'; @@ -29,7 +30,6 @@ import { } from './utils/compiler'; import { constants } from './utils/constants'; import { fsWrapper } from './utils/fs_wrapper'; -import { CompilerOptions, ContractArtifact, ContractVersionData } from './utils/types'; import { utils } from './utils/utils'; type TYPE_ALL_FILES_IDENTIFIER = '*'; -- cgit v1.2.3 From 4779ebfd20d9c4b197d525453ac1ec47cc15e2bc Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 22 Aug 2018 17:32:01 -0400 Subject: split method --- packages/sol-compiler/src/compiler.ts | 51 ++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 7c76f3e52..c44585a36 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -110,6 +110,21 @@ export class Compiler { const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); return { solcInstance, fullSolcVersion }; } + private static _addHexPrefixes(compiledData: solc.StandardContractOutput): void { + if (!_.isUndefined(compiledData.evm)) { + if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) { + compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object); + } + if ( + !_.isUndefined(compiledData.evm.deployedBytecode) && + !_.isUndefined(compiledData.evm.deployedBytecode.object) + ) { + compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix( + compiledData.evm.deployedBytecode.object, + ); + } + } + } /** * Instantiates a new instance of the Compiler class. * @param opts Optional compiler options @@ -214,11 +229,22 @@ export class Compiler { const compilerOutput = this._compile(solcInstance, input.standardInput); for (const contractPath of input.contractsToCompile) { - await this._verifyAndPersistCompiledContractAsync( + const contractName = contractPathToData[contractPath].contractName; + + const compiledData = compilerOutput.contracts[contractPath][contractName]; + if (_.isUndefined(compiledData)) { + throw new Error( + `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, + ); + } + + Compiler._addHexPrefixes(compiledData); + + await this._persistCompiledContractAsync( contractPath, contractPathToData[contractPath].currentArtifactIfExists, contractPathToData[contractPath].sourceTreeHashHex, - contractPathToData[contractPath].contractName, + contractName, fullSolcVersion, compilerOutput, ); @@ -236,7 +262,7 @@ export class Compiler { return !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } } - private async _verifyAndPersistCompiledContractAsync( + private async _persistCompiledContractAsync( contractPath: string, currentArtifactIfExists: ContractArtifact | void, sourceTreeHashHex: string, @@ -245,25 +271,6 @@ export class Compiler { compilerOutput: solc.StandardOutput, ): Promise { const compiledData = compilerOutput.contracts[contractPath][contractName]; - if (_.isUndefined(compiledData)) { - throw new Error( - `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, - ); - } - if (!_.isUndefined(compiledData.evm)) { - if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) { - compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object); - } - if ( - !_.isUndefined(compiledData.evm.deployedBytecode) && - !_.isUndefined(compiledData.evm.deployedBytecode.object) - ) { - compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix( - compiledData.evm.deployedBytecode.object, - ); - } - } - const sourceCodes = _.mapValues( compilerOutput.sources, (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, -- cgit v1.2.3 From 5c056b57b7c16c2c7a27143dcfd1e7a340a191a9 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 22 Aug 2018 17:47:40 -0400 Subject: extract method _getContractNamesToCompile() --- packages/sol-compiler/src/compiler.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index c44585a36..bc6243a8f 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -159,16 +159,17 @@ export class Compiler { public async compileAsync(): Promise { await createDirIfDoesNotExistAsync(this._artifactsDir); await createDirIfDoesNotExistAsync(SOLC_BIN_DIR); - let contractNamesToCompile: string[] = []; + await this._compileContractsAsync(this._getContractNamesToCompile()); + } + private _getContractNamesToCompile(): string[] { if (this._specifiedContracts === ALL_CONTRACTS_IDENTIFIER) { const allContracts = this._nameResolver.getAll(); - contractNamesToCompile = _.map(allContracts, contractSource => + return _.map(allContracts, contractSource => path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION), ); } else { - contractNamesToCompile = this._specifiedContracts; + return this._specifiedContracts; } - await this._compileContractsAsync(contractNamesToCompile); } /** * Compiles contract and saves artifact to artifactsDir. -- cgit v1.2.3 From 80ed724f3abd019dc1bcaa9e2a0f02d69c8f6649 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 23 Aug 2018 12:07:23 -0400 Subject: rename var `compiledData` to `compiledContract` --- packages/sol-compiler/src/compiler.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index bc6243a8f..cf406b583 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -110,17 +110,17 @@ export class Compiler { const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); return { solcInstance, fullSolcVersion }; } - private static _addHexPrefixes(compiledData: solc.StandardContractOutput): void { - if (!_.isUndefined(compiledData.evm)) { - if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) { - compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object); + private static _addHexPrefixes(compiledContract: solc.StandardContractOutput): void { + if (!_.isUndefined(compiledContract.evm)) { + if (!_.isUndefined(compiledContract.evm.bytecode) && !_.isUndefined(compiledContract.evm.bytecode.object)) { + compiledContract.evm.bytecode.object = ethUtil.addHexPrefix(compiledContract.evm.bytecode.object); } if ( - !_.isUndefined(compiledData.evm.deployedBytecode) && - !_.isUndefined(compiledData.evm.deployedBytecode.object) + !_.isUndefined(compiledContract.evm.deployedBytecode) && + !_.isUndefined(compiledContract.evm.deployedBytecode.object) ) { - compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix( - compiledData.evm.deployedBytecode.object, + compiledContract.evm.deployedBytecode.object = ethUtil.addHexPrefix( + compiledContract.evm.deployedBytecode.object, ); } } @@ -232,14 +232,14 @@ export class Compiler { for (const contractPath of input.contractsToCompile) { const contractName = contractPathToData[contractPath].contractName; - const compiledData = compilerOutput.contracts[contractPath][contractName]; - if (_.isUndefined(compiledData)) { + const compiledContract = compilerOutput.contracts[contractPath][contractName]; + if (_.isUndefined(compiledContract)) { throw new Error( `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, ); } - Compiler._addHexPrefixes(compiledData); + Compiler._addHexPrefixes(compiledContract); await this._persistCompiledContractAsync( contractPath, @@ -271,13 +271,13 @@ export class Compiler { fullSolcVersion: string, compilerOutput: solc.StandardOutput, ): Promise { - const compiledData = compilerOutput.contracts[contractPath][contractName]; + const compiledContract = compilerOutput.contracts[contractPath][contractName]; const sourceCodes = _.mapValues( compilerOutput.sources, (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, ); const contractVersion: ContractVersionData = { - compilerOutput: compiledData, + compilerOutput: compiledContract, sources: compilerOutput.sources, sourceCodes, sourceTreeHashHex, -- cgit v1.2.3 From 849e203812aacff453228a372143600b05155a2c Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 22 Aug 2018 17:52:28 -0400 Subject: add interface to return compiler output... ...rather than persisting it to the filesystem. --- packages/sol-compiler/src/compiler.ts | 44 ++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index cf406b583..91b17c4f2 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -159,7 +159,18 @@ export class Compiler { public async compileAsync(): Promise { await createDirIfDoesNotExistAsync(this._artifactsDir); await createDirIfDoesNotExistAsync(SOLC_BIN_DIR); - await this._compileContractsAsync(this._getContractNamesToCompile()); + await this._compileContractsAsync(this._getContractNamesToCompile(), true); + } + /** + * Compiles Solidity files specified during construction, and returns the + * compiler output given by solc. Return value is an array of outputs: + * Solidity modules are batched together by version required, and each + * element of the returned array corresponds to a compiler version, and + * each element contains the output for all of the modules compiled with + * that version. + */ + public async getCompilerOutputsAsync(): Promise { + return this._compileContractsAsync(this._getContractNamesToCompile(), false); } private _getContractNamesToCompile(): string[] { if (this._specifiedContracts === ALL_CONTRACTS_IDENTIFIER) { @@ -172,10 +183,14 @@ export class Compiler { } } /** - * Compiles contract and saves artifact to artifactsDir. + * Compiles contracts, and, if `shouldPersist` is true, saves artifacts to artifactsDir. * @param fileName Name of contract with '.sol' extension. + * @return an array of compiler outputs, where each element corresponds to a different version of solc-js. */ - private async _compileContractsAsync(contractNames: string[]): Promise { + private async _compileContractsAsync( + contractNames: string[], + shouldPersist: boolean, + ): Promise { // batch input contracts together based on the version of the compiler that they require. const versionToInputs: VersionToInputs = {}; @@ -216,6 +231,8 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } + const compilerOutputs: solc.StandardOutput[] = []; + const solcVersions = _.keys(versionToInputs); for (const solcVersion of solcVersions) { const input = versionToInputs[solcVersion]; @@ -228,6 +245,7 @@ export class Compiler { const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion); const compilerOutput = this._compile(solcInstance, input.standardInput); + compilerOutputs.push(compilerOutput); for (const contractPath of input.contractsToCompile) { const contractName = contractPathToData[contractPath].contractName; @@ -241,16 +259,20 @@ export class Compiler { Compiler._addHexPrefixes(compiledContract); - await this._persistCompiledContractAsync( - contractPath, - contractPathToData[contractPath].currentArtifactIfExists, - contractPathToData[contractPath].sourceTreeHashHex, - contractName, - fullSolcVersion, - compilerOutput, - ); + if (shouldPersist) { + await this._persistCompiledContractAsync( + contractPath, + contractPathToData[contractPath].currentArtifactIfExists, + contractPathToData[contractPath].sourceTreeHashHex, + contractName, + fullSolcVersion, + compilerOutput, + ); + } } } + + return compilerOutputs; } private _shouldCompile(contractData: ContractData): boolean { if (_.isUndefined(contractData.currentArtifactIfExists)) { -- cgit v1.2.3 From a1959df911741d0424a952fa4a63c5dcc1135524 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 24 Aug 2018 09:18:33 -0400 Subject: add devdoc support to solc typings, and use it --- packages/sol-compiler/src/compiler.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 91b17c4f2..b5255b361 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -10,7 +10,7 @@ import { } from '@0xproject/sol-resolver'; import { fetchAsync, logUtils } from '@0xproject/utils'; import chalk from 'chalk'; -import { CompilerOptions, ContractArtifact, ContractVersionData } from 'ethereum-types'; +import { CompilerOptions, ContractArtifact, ContractVersionData, StandardOutput } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as fs from 'fs'; import * as _ from 'lodash'; @@ -169,7 +169,7 @@ export class Compiler { * each element contains the output for all of the modules compiled with * that version. */ - public async getCompilerOutputsAsync(): Promise { + public async getCompilerOutputsAsync(): Promise { return this._compileContractsAsync(this._getContractNamesToCompile(), false); } private _getContractNamesToCompile(): string[] { @@ -187,10 +187,7 @@ export class Compiler { * @param fileName Name of contract with '.sol' extension. * @return an array of compiler outputs, where each element corresponds to a different version of solc-js. */ - private async _compileContractsAsync( - contractNames: string[], - shouldPersist: boolean, - ): Promise { + private async _compileContractsAsync(contractNames: string[], shouldPersist: boolean): Promise { // batch input contracts together based on the version of the compiler that they require. const versionToInputs: VersionToInputs = {}; @@ -231,7 +228,7 @@ export class Compiler { versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - const compilerOutputs: solc.StandardOutput[] = []; + const compilerOutputs: StandardOutput[] = []; const solcVersions = _.keys(versionToInputs); for (const solcVersion of solcVersions) { -- cgit v1.2.3 From 6450844d7fc39561671dd72f036a436f8bc2f664 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 30 Aug 2018 08:59:30 -0400 Subject: rename method _addHexPrefixes --- packages/sol-compiler/src/compiler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index b5255b361..ced139909 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -110,7 +110,7 @@ export class Compiler { const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); return { solcInstance, fullSolcVersion }; } - private static _addHexPrefixes(compiledContract: solc.StandardContractOutput): void { + private static _addHexPrefixToContractBytecode(compiledContract: solc.StandardContractOutput): void { if (!_.isUndefined(compiledContract.evm)) { if (!_.isUndefined(compiledContract.evm.bytecode) && !_.isUndefined(compiledContract.evm.bytecode.object)) { compiledContract.evm.bytecode.object = ethUtil.addHexPrefix(compiledContract.evm.bytecode.object); @@ -254,7 +254,7 @@ export class Compiler { ); } - Compiler._addHexPrefixes(compiledContract); + Compiler._addHexPrefixToContractBytecode(compiledContract); if (shouldPersist) { await this._persistCompiledContractAsync( -- cgit v1.2.3 From 29f2ae605edadedbd150cc6df7aafffdef6a48a3 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 30 Aug 2018 09:02:00 -0400 Subject: re-word comment: 'construction' -> 'instantiation' --- packages/sol-compiler/src/compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index ced139909..d2977c691 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -162,7 +162,7 @@ export class Compiler { await this._compileContractsAsync(this._getContractNamesToCompile(), true); } /** - * Compiles Solidity files specified during construction, and returns the + * Compiles Solidity files specified during instantiation, and returns the * compiler output given by solc. Return value is an array of outputs: * Solidity modules are batched together by version required, and each * element of the returned array corresponds to a compiler version, and -- cgit v1.2.3 From 6273339f7c588f31f6c664a6aa3b58e2b94b9051 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 30 Aug 2018 09:54:10 -0400 Subject: add named references for returned objects --- packages/sol-compiler/src/compiler.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index d2977c691..3b0bd90f9 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -170,17 +170,20 @@ export class Compiler { * that version. */ public async getCompilerOutputsAsync(): Promise { - return this._compileContractsAsync(this._getContractNamesToCompile(), false); + const promisedOutputs = this._compileContractsAsync(this._getContractNamesToCompile(), false); + return promisedOutputs; } private _getContractNamesToCompile(): string[] { + let contractNamesToCompile; if (this._specifiedContracts === ALL_CONTRACTS_IDENTIFIER) { const allContracts = this._nameResolver.getAll(); - return _.map(allContracts, contractSource => + contractNamesToCompile = _.map(allContracts, contractSource => path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION), ); } else { - return this._specifiedContracts; + contractNamesToCompile = this._specifiedContracts; } + return contractNamesToCompile; } /** * Compiles contracts, and, if `shouldPersist` is true, saves artifacts to artifactsDir. -- cgit v1.2.3 From 3e5d427d4e873080f2a369db7f844cbadd610fcb Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 21 Sep 2018 10:56:17 -0400 Subject: feat: add sol-doc command-line interface modified sol-compiler to output progress/warning/error/etc messages to stderr rather than stdout, so that sol-doc can put its output (and nothing else) to stdout. for posterity, added sol-doc cli usage as npm scripts to package.json. --- packages/sol-compiler/src/compiler.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3b0bd90f9..a29367485 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -94,7 +94,7 @@ export class Compiler { if (await fsWrapper.doesFileExistAsync(compilerBinFilename)) { solcjs = (await fsWrapper.readFileAsync(compilerBinFilename)).toString(); } else { - logUtils.log(`Downloading ${fullSolcVersion}...`); + logUtils.warn(`Downloading ${fullSolcVersion}...`); const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; const response = await fetchAsync(url); const SUCCESS_STATUS = 200; @@ -181,7 +181,9 @@ export class Compiler { path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION), ); } else { - contractNamesToCompile = this._specifiedContracts; + contractNamesToCompile = this._specifiedContracts.map(specifiedContract => + path.basename(specifiedContract, constants.SOLIDITY_FILE_EXTENSION), + ); } return contractNamesToCompile; } @@ -236,7 +238,7 @@ export class Compiler { const solcVersions = _.keys(versionToInputs); for (const solcVersion of solcVersions) { const input = versionToInputs[solcVersion]; - logUtils.log( + logUtils.warn( `Compiling ${input.contractsToCompile.length} contracts (${ input.contractsToCompile }) with Solidity v${solcVersion}...`, @@ -329,7 +331,7 @@ export class Compiler { const artifactString = utils.stringifyWithFormatting(newArtifact); const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`; await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); - logUtils.log(`${contractName} artifact saved!`); + logUtils.warn(`${contractName} artifact saved!`); } private _compile(solcInstance: solc.SolcInstance, standardInput: solc.StandardInput): solc.StandardOutput { const compiled: solc.StandardOutput = JSON.parse( @@ -345,13 +347,13 @@ export class Compiler { if (!_.isEmpty(errors)) { errors.forEach(error => { const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); - logUtils.log(chalk.red(normalizedErrMsg)); + logUtils.warn(chalk.red(normalizedErrMsg)); }); throw new Error('Compilation errors encountered'); } else { warnings.forEach(warning => { const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); - logUtils.log(chalk.yellow(normalizedWarningMsg)); + logUtils.warn(chalk.yellow(normalizedWarningMsg)); }); } } -- cgit v1.2.3 From 98c1952956d87adf5e73a42a1b78b8bf8b4119d2 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Tue, 2 Oct 2018 15:00:35 -0400 Subject: fix: persist artifacts with only relevant sources https://github.com/0xProject/0x-monorepo/pull/1108 https://app.asana.com/0/684263176955174/842516551768097/f --- packages/sol-compiler/src/compiler.ts | 57 ++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index a29367485..350a5a125 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -296,13 +296,12 @@ export class Compiler { compilerOutput: solc.StandardOutput, ): Promise { const compiledContract = compilerOutput.contracts[contractPath][contractName]; - const sourceCodes = _.mapValues( - compilerOutput.sources, - (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, - ); + + const { sourceCodes, sources } = this._getSourcesWithDependencies(contractPath); + const contractVersion: ContractVersionData = { compilerOutput: compiledContract, - sources: compilerOutput.sources, + sources, sourceCodes, sourceTreeHashHex, compiler: { @@ -333,6 +332,54 @@ export class Compiler { await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); logUtils.warn(`${contractName} artifact saved!`); } + private _getSourcesWithDependencies( + contractPath: string, + ): { sourceCodes: { [sourceName: string]: string }; sources: { [sourceName: string]: { id: number } } } { + const sources = { [contractPath]: { id: 0 } }; + const sourceCodes = { [contractPath]: this._resolver.resolve(contractPath).source }; + this._recursivelyGatherDependencySources(contractPath, sourceCodes[contractPath], sources, sourceCodes, 1); + return { sourceCodes, sources }; + } + private _recursivelyGatherDependencySources( + contractPath: string, + contractSource: string, + sourcesToAppendTo: { [sourceName: string]: { id: number } }, + sourceCodesToAppendTo: { [sourceName: string]: string }, + nextId: number, + ): number { + let nextId_ = nextId; + + const importStatementMatches = contractSource.match(/import[^;]*;/g); + if (importStatementMatches === null) { + return nextId_; + } + for (const importStatementMatch of importStatementMatches) { + const importPathMatches = importStatementMatch.match(/\"([^\"]*)\"/); + if (importPathMatches === null || importPathMatches.length === 0) { + continue; + } + + let importPath = importPathMatches[1]; + const lastPathSeparatorPos = contractPath.lastIndexOf('/'); + const importFolder = lastPathSeparatorPos === -1 ? '' : contractPath.slice(0, lastPathSeparatorPos + 1); + importPath = importPath.slice(0, 2) === './' ? importPath.replace(/^.\//, importFolder) : importPath; + + if (_.isUndefined(sourcesToAppendTo[importPath])) { + sourcesToAppendTo[importPath] = { id: nextId_ }; + sourceCodesToAppendTo[importPath] = this._resolver.resolve(importPath).source; + nextId_ += 1; + + nextId_ = this._recursivelyGatherDependencySources( + importPath, + this._resolver.resolve(importPath).source, + sourcesToAppendTo, + sourceCodesToAppendTo, + nextId_, + ); + } + } + return nextId_; + } private _compile(solcInstance: solc.SolcInstance, standardInput: solc.StandardInput): solc.StandardOutput { const compiled: solc.StandardOutput = JSON.parse( solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { -- cgit v1.2.3 From 37c55302e74d6a6706a390fe03432c0d3f119510 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Tue, 2 Oct 2018 17:29:47 -0700 Subject: Fix some small bugs in compiler.ts --- packages/sol-compiler/src/compiler.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 350a5a125..ea080c312 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -349,7 +349,7 @@ export class Compiler { ): number { let nextId_ = nextId; - const importStatementMatches = contractSource.match(/import[^;]*;/g); + const importStatementMatches = contractSource.match(/\nimport[^;]*;/g); if (importStatementMatches === null) { return nextId_; } @@ -360,9 +360,24 @@ export class Compiler { } let importPath = importPathMatches[1]; + // HACK(ablrow): We have, e.g.: + // + // importPath = "../../utils/LibBytes/LibBytes.sol" + // contractPath = "2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol" + // + // Resolver doesn't understand "../" so we want to pass + // "2.0.0/utils/LibBytes/LibBytes.sol" to resolver. + // + // This hack involves using path.resolve. But path.resolve returns + // absolute directories by default. We trick it into thinking that + // contractPath is a root directory by prepending a '/' and then + // removing the '/' the end. + // + // path.resolve("/a/b/c", ""../../d/e") === "/a/d/e" + // const lastPathSeparatorPos = contractPath.lastIndexOf('/'); - const importFolder = lastPathSeparatorPos === -1 ? '' : contractPath.slice(0, lastPathSeparatorPos + 1); - importPath = importPath.slice(0, 2) === './' ? importPath.replace(/^.\//, importFolder) : importPath; + const contractFolder = lastPathSeparatorPos === -1 ? '' : contractPath.slice(0, lastPathSeparatorPos + 1); + importPath = path.resolve('/' + contractFolder, importPath).replace('/', ''); if (_.isUndefined(sourcesToAppendTo[importPath])) { sourcesToAppendTo[importPath] = { id: nextId_ }; -- cgit v1.2.3 From 39a336ca6d6879ad6413cee714d929cb99bcd968 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 3 Oct 2018 10:44:19 -0400 Subject: fix: use original source ID's from compiler output Previously, was generating fresh source ID's but per @LogvinovLeon 's comment (cited below) that will likely break existing source code mappings. Changed to use the original source code mapping ID's that were generated by the compiler https://app.asana.com/0/684263176955174/842516551768097/f https://github.com/0xProject/0x-monorepo/pull/1108 https://github.com/0xProject/0x-monorepo/pull/1108#pullrequestreview-161059063 --- packages/sol-compiler/src/compiler.ts | 37 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index ea080c312..620728ed2 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -297,7 +297,7 @@ export class Compiler { ): Promise { const compiledContract = compilerOutput.contracts[contractPath][contractName]; - const { sourceCodes, sources } = this._getSourcesWithDependencies(contractPath); + const { sourceCodes, sources } = this._getSourcesWithDependencies(contractPath, compilerOutput.sources); const contractVersion: ContractVersionData = { compilerOutput: compiledContract, @@ -332,26 +332,39 @@ export class Compiler { await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); logUtils.warn(`${contractName} artifact saved!`); } + /** + * For the given @param contractPath, populates JSON objects to be used in the ContractArtifact interface's + * properties `sources` (source code file names mapped to ID numbers) and `sourceCodes` (source code content of + * contracts) for that contract. The source code pointed to by contractPath is read and parsed directly (via + * `this._resolver.resolve().source`), as are its imports, recursively. The ID numbers for @return `sources` are + * taken from the corresponding ID's in @param fullSources, and the content for @return sourceCodes is read from + * disk (via the aforementioned `resolver.source`). + */ private _getSourcesWithDependencies( contractPath: string, + fullSources: { [sourceName: string]: { id: number } }, ): { sourceCodes: { [sourceName: string]: string }; sources: { [sourceName: string]: { id: number } } } { - const sources = { [contractPath]: { id: 0 } }; + const sources = { [contractPath]: { id: fullSources[contractPath].id } }; const sourceCodes = { [contractPath]: this._resolver.resolve(contractPath).source }; - this._recursivelyGatherDependencySources(contractPath, sourceCodes[contractPath], sources, sourceCodes, 1); + this._recursivelyGatherDependencySources( + contractPath, + sourceCodes[contractPath], + fullSources, + sources, + sourceCodes, + ); return { sourceCodes, sources }; } private _recursivelyGatherDependencySources( contractPath: string, contractSource: string, + fullSources: { [sourceName: string]: { id: number } }, sourcesToAppendTo: { [sourceName: string]: { id: number } }, sourceCodesToAppendTo: { [sourceName: string]: string }, - nextId: number, - ): number { - let nextId_ = nextId; - + ): void { const importStatementMatches = contractSource.match(/\nimport[^;]*;/g); if (importStatementMatches === null) { - return nextId_; + return; } for (const importStatementMatch of importStatementMatches) { const importPathMatches = importStatementMatch.match(/\"([^\"]*)\"/); @@ -380,20 +393,18 @@ export class Compiler { importPath = path.resolve('/' + contractFolder, importPath).replace('/', ''); if (_.isUndefined(sourcesToAppendTo[importPath])) { - sourcesToAppendTo[importPath] = { id: nextId_ }; + sourcesToAppendTo[importPath] = { id: fullSources[importPath].id }; sourceCodesToAppendTo[importPath] = this._resolver.resolve(importPath).source; - nextId_ += 1; - nextId_ = this._recursivelyGatherDependencySources( + this._recursivelyGatherDependencySources( importPath, this._resolver.resolve(importPath).source, + fullSources, sourcesToAppendTo, sourceCodesToAppendTo, - nextId_, ); } } - return nextId_; } private _compile(solcInstance: solc.SolcInstance, standardInput: solc.StandardInput): solc.StandardOutput { const compiled: solc.StandardOutput = JSON.parse( -- cgit v1.2.3 From f614a2425f79c0ba4982b0868ed6edd9c491ef1b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 3 Oct 2018 10:57:37 -0400 Subject: fix: comment need for sourceCodes pruning --- packages/sol-compiler/src/compiler.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'packages/sol-compiler/src/compiler.ts') diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 620728ed2..7eefc1474 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -297,6 +297,10 @@ export class Compiler { ): Promise { const compiledContract = compilerOutput.contracts[contractPath][contractName]; + // need to gather sourceCodes for this artifact, but compilerOutput.sources (the list of contract modules) + // contains listings for for every contract compiled during the compiler invocation that compiled the contract + // to be persisted, which could include many that are irrelevant to the contract at hand. So, gather up only + // the relevant sources: const { sourceCodes, sources } = this._getSourcesWithDependencies(contractPath, compilerOutput.sources); const contractVersion: ContractVersionData = { @@ -333,7 +337,7 @@ export class Compiler { logUtils.warn(`${contractName} artifact saved!`); } /** - * For the given @param contractPath, populates JSON objects to be used in the ContractArtifact interface's + * For the given @param contractPath, populates JSON objects to be used in the ContractVersionData interface's * properties `sources` (source code file names mapped to ID numbers) and `sourceCodes` (source code content of * contracts) for that contract. The source code pointed to by contractPath is read and parsed directly (via * `this._resolver.resolve().source`), as are its imports, recursively. The ID numbers for @return `sources` are -- cgit v1.2.3