js: Add stats and override options (#348)

- Add `RESOLC_BIN` env variable to force use a binary compiler instead
of the wasm
- Add `--diff-stats` options to print file path 

e.g

```
~/github/redstone-oracles-monorepo main*
❯ npx @parity/resolc@latest --diff-stats \
  --base-path . \
  --include-path node_modules \
  --bin packages/evm-connector/contracts/samples/SampleWithEvents.sol
┌─────────┬──────────────────────────────────────────────────────────────────────────┬───────────────────────────────┬────────────┬────────────┬───────────┐
│ (index) │ file                                                                     │ contract                      │ polkavm    │ bin        │ diff      │
├─────────┼──────────────────────────────────────────────────────────────────────────┼───────────────────────────────┼────────────┼────────────┼───────────┤
│ 0       │ 'packages/evm-connector/contracts/core/CalldataExtractor.sol'            │ 'CalldataExtractor'           │ '4.31 kB'  │ '2.53 kB'  │ '70.12%'  │
│ 1       │ 'packages/evm-connector/contracts/core/RedstoneConstants.sol'            │ 'RedstoneConstants'           │ '0.80 kB'  │ '0.17 kB'  │ '368.18%' │
│ 2       │ 'packages/evm-connector/contracts/core/RedstoneDefaultsLib.sol'          │ 'RedstoneDefaultsLib'         │ '0.90 kB'  │ '0.31 kB'  │ '189.06%' │
│ 3       │ 'packages/evm-connector/contracts/libs/BitmapLib.sol'                    │ 'BitmapLib'                   │ '0.90 kB'  │ '0.31 kB'  │ '189.06%' │
│ 4       │ 'packages/evm-connector/contracts/libs/NumericArrayLib.sol'              │ 'NumericArrayLib'             │ '0.90 kB'  │ '0.31 kB'  │ '189.06%' │
│ 5       │ 'packages/evm-connector/contracts/libs/SignatureLib.sol'                 │ 'SignatureLib'                │ '0.90 kB'  │ '0.31 kB'  │ '189.06%' │
│ 6       │ 'packages/evm-connector/contracts/mocks/RedstoneConsumerNumericMock.sol' │ 'RedstoneConsumerNumericMock' │ '13.62 kB' │ '10.17 kB' │ '33.96%'  │
│ 7       │ 'packages/evm-connector/contracts/samples/SampleWithEvents.sol'          │ 'SampleWithEvents'            │ '29.34 kB' │ '15.60 kB' │ '88.03%'  │
└─────────┴──────────────────────────────────────────────────────────────────────────┴───────────────────────────────┴────────────┴────────────┴───────────┘
```
This commit is contained in:
PG Herveou
2025-06-19 12:17:09 +02:00
committed by GitHub
parent 8754d802fa
commit 7656c6a8b4
2 changed files with 57 additions and 16 deletions
+55 -10
View File
@@ -6,6 +6,7 @@ import * as os from 'os'
import * as path from 'path'
import * as resolc from '.'
import { SolcInput } from '.'
import { execSync } from 'child_process'
async function main() {
// hold on to any exception handlers that existed prior to this script running, we'll be adding them back at the end
@@ -17,11 +18,15 @@ async function main() {
const program = new commander.Command()
program.name('solcjs')
program.name('resolcjs')
program.version(resolc.version())
program
.option('--bin', 'Binary of the contracts in hex.')
.option('--abi', 'ABI of the contracts.')
.option(
'--diff-stats',
'Print statistics about Resolc vs Solc compilation.'
)
.option(
'--base-path <path>',
'Root of the project source tree. ' +
@@ -49,8 +54,20 @@ async function main() {
outputDir?: string
prettyJson: boolean
basePath?: string
diffStats: boolean
includePath?: string[]
}>()
// when using --stats option, we want to run solc as well to compare outputs size
if (options.diffStats) {
const args = process.argv.filter((arg) => !arg.startsWith('--diff-stats'))
try {
execSync(`npx --yes solc@latest ${args.slice(2).join(' ')}`)
} catch (err) {
abort(`Failed to run solc: ${err}`)
}
}
const files: string[] = program.args
const destination = options.outputDir ?? '.'
@@ -137,7 +154,7 @@ async function main() {
if (!output) {
abort('No output from compiler')
} else if (output.errors) {
} else if (output.errors && !options.diffStats) {
for (const error in output.errors) {
const message = output.errors[error]
if (message.severity === 'warning') {
@@ -160,19 +177,41 @@ async function main() {
})
}
const contractStats = []
for (const fileName in output.contracts) {
for (const contractName in output.contracts[fileName]) {
let contractFileName = fileName + ':' + contractName
contractFileName = contractFileName.replace(/[:./\\]/g, '_')
if (options.bin) {
writeFile(
contractFileName + '.polkavm',
Buffer.from(
output.contracts[fileName][contractName].evm.bytecode.object,
'hex'
)
let polkavmSize = 0
let binSize = 0
if (
options.bin &&
output.contracts?.[fileName]?.[contractName]?.evm?.bytecode?.object
) {
const pvmData = Buffer.from(
output.contracts[fileName][contractName].evm.bytecode.object,
'hex'
)
writeFile(contractFileName + '.polkavm', pvmData)
polkavmSize = pvmData.length
const binOutPath = path.join(destination, `${contractFileName}.bin`)
if (fs.existsSync(binOutPath)) {
try {
binSize = fs.statSync(binOutPath).size || 0
} catch {}
}
contractStats.push({
file: fileName,
contract: contractName,
['resolc (kB)']: Number((polkavmSize / 1024).toFixed(2)),
['solc (kB)']: Number((binSize / 1024).toFixed(2)),
['diff (%)']:
binSize > 0
? Number(((polkavmSize / binSize - 1) * 100).toFixed(2))
: Number.NaN,
})
}
if (options.abi) {
@@ -184,6 +223,12 @@ async function main() {
}
}
if (options.diffStats && contractStats.length > 0) {
console.table(
contractStats.sort((a, b) => b['resolc (kB)'] - a['resolc (kB)'])
)
}
// Put back original exception handlers.
originalUncaughtExceptionListeners.forEach(function (listener) {
process.addListener('uncaughtException', listener)
+2 -6
View File
@@ -50,11 +50,7 @@ export function resolveInputs(sources: SolcInput): SolcInput {
language: 'Solidity',
sources,
settings: {
outputSelection: {
'*': {
'*': ['evm.bytecode.object'],
},
},
outputSelection: {}, // no outputs requested, only resolves imports
},
}
@@ -106,7 +102,7 @@ export async function compile(
enabled: true,
runs: 200,
},
bin,
bin = process.env.RESOLC_BIN,
} = option
const input = JSON.stringify({