Commit 70ff6476 authored by kf's avatar kf Committed by Kelvin Fichter

feat: move surgery solc cache to disk

Signed-off-by: default avatarkf <kelvin@optimism.io>
parent fc97fb87
module.exports = { module.exports = {
extends: '../../.eslintrc.js', extends: '../../.eslintrc.js',
ignorePatterns: ['/data', '/solc-bin'], ignorePatterns: ['/data', '/solc-bin', '/solc-cache'],
} }
...@@ -5,3 +5,4 @@ outputs/ ...@@ -5,3 +5,4 @@ outputs/
etherscan/ etherscan/
state-dumps/ state-dumps/
data/ data/
solc-cache/
...@@ -146,3 +146,15 @@ export const SOLC_BIN_PATH = 'https://binaries.soliditylang.org' ...@@ -146,3 +146,15 @@ export const SOLC_BIN_PATH = 'https://binaries.soliditylang.org'
export const EMSCRIPTEN_BUILD_PATH = `${SOLC_BIN_PATH}/emscripten-wasm32` export const EMSCRIPTEN_BUILD_PATH = `${SOLC_BIN_PATH}/emscripten-wasm32`
export const EMSCRIPTEN_BUILD_LIST = `${EMSCRIPTEN_BUILD_PATH}/list.json` export const EMSCRIPTEN_BUILD_LIST = `${EMSCRIPTEN_BUILD_PATH}/list.json`
export const LOCAL_SOLC_DIR = path.join(__dirname, '..', 'solc-bin') export const LOCAL_SOLC_DIR = path.join(__dirname, '..', 'solc-bin')
export const EVM_SOLC_CACHE_DIR = path.join(
__dirname,
'..',
'solc-cache',
'evm'
)
export const OVM_SOLC_CACHE_DIR = path.join(
__dirname,
'..',
'solc-cache',
'ovm'
)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { access, mkdir } from 'fs/promises' import { access, mkdir } from 'fs/promises'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import path from 'path' import path from 'path'
import fs from 'fs' import fs, { mkdirSync } from 'fs'
import solc from 'solc' import solc from 'solc'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { clone } from '@eth-optimism/core-utils' import { clone } from '@eth-optimism/core-utils'
...@@ -11,6 +11,8 @@ import { ...@@ -11,6 +11,8 @@ import {
EMSCRIPTEN_BUILD_LIST, EMSCRIPTEN_BUILD_LIST,
EMSCRIPTEN_BUILD_PATH, EMSCRIPTEN_BUILD_PATH,
LOCAL_SOLC_DIR, LOCAL_SOLC_DIR,
EVM_SOLC_CACHE_DIR,
OVM_SOLC_CACHE_DIR,
} from './constants' } from './constants'
import { EtherscanContract } from './types' import { EtherscanContract } from './types'
...@@ -181,10 +183,50 @@ const compilerCache: { ...@@ -181,10 +183,50 @@ const compilerCache: {
['EVM']: {}, ['EVM']: {},
} }
const readCompilerCache = (
target: 'evm' | 'ovm',
hash: string
): any | undefined => {
try {
const cacheDir = target === 'evm' ? EVM_SOLC_CACHE_DIR : OVM_SOLC_CACHE_DIR
return JSON.parse(
fs.readFileSync(path.join(cacheDir, hash), {
encoding: 'utf-8',
})
)
} catch (err) {
return undefined
}
}
const writeCompilerCache = (
target: 'evm' | 'ovm',
hash: string,
content: any
) => {
const cacheDir = target === 'evm' ? EVM_SOLC_CACHE_DIR : OVM_SOLC_CACHE_DIR
fs.writeFileSync(path.join(cacheDir, hash), JSON.stringify(content))
}
export const compile = (opts: { export const compile = (opts: {
contract: EtherscanContract contract: EtherscanContract
ovm: boolean ovm: boolean
}): any => { }): any => {
try {
mkdirSync(EVM_SOLC_CACHE_DIR, {
recursive: true,
})
} catch (e) {
// directory already exists
}
try {
mkdirSync(OVM_SOLC_CACHE_DIR, {
recursive: true,
})
} catch (e) {
// directory already exists
}
let version: string let version: string
if (opts.ovm) { if (opts.ovm) {
version = opts.contract.compilerVersion version = opts.contract.compilerVersion
...@@ -200,17 +242,15 @@ export const compile = (opts: { ...@@ -200,17 +242,15 @@ export const compile = (opts: {
const solcInstance = getSolc(version, opts.ovm) const solcInstance = getSolc(version, opts.ovm)
const input = JSON.stringify(solcInput(opts.contract)) const input = JSON.stringify(solcInput(opts.contract))
const inputHash = ethers.utils.solidityKeccak256(['string'], [input]) const inputHash = ethers.utils.solidityKeccak256(['string'], [input])
const compilerTarget = opts.ovm ? 'OVM' : 'EVM' const compilerTarget = opts.ovm ? 'ovm' : 'evm'
// Cache the compiler output to speed up repeated compilations of the same contract. If this // Cache the compiler output to speed up repeated compilations of the same contract. If this
// cache is too memory intensive, then we could consider only caching if the contract has been // cache is too memory intensive, then we could consider only caching if the contract has been
// seen more than once. // seen more than once.
let output: any let output = readCompilerCache(compilerTarget, inputHash)
if (compilerCache[compilerTarget][inputHash]) { if (output === undefined) {
output = compilerCache[compilerTarget][inputHash]
} else {
output = JSON.parse(solcInstance.compile(input)) output = JSON.parse(solcInstance.compile(input))
compilerCache[compilerTarget][inputHash] = output writeCompilerCache(compilerTarget, inputHash, output)
} }
if (!output.contracts) { if (!output.contracts) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment