Skip to content

Commit b2c8425

Browse files
committed
Scripts for generating and comparing bytecode reports for solc-bin binaries
1 parent 5b85da1 commit b2c8425

File tree

2 files changed

+197
-0
lines changed

2 files changed

+197
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env bash
2+
3+
# ------------------------------------------------------------------------------
4+
# Determines versions of all release binaries from solc-bin repo modified in the
5+
# specified commit range, finds all release binaries from one, selected platform
6+
# that match these versions and uses them to produce bytecode reports.
7+
#
8+
# The script is meant to be backwards-compatible with older versions of the
9+
# compiler. Reports are generated via the CLI interface (rather than Standard
10+
# JSON) in case of native binaries because the JSON interface was not available
11+
# in very old versions.
12+
#
13+
# The script creates one report per binary and file names follow the pattern
14+
# 'report-<binary name>.txt'.
15+
#
16+
# Usage:
17+
# <script name>.sh <PLATFORM> <BASE_REF> <TOP_REF> <SOLC_BIN_DIR> <SOLIDITY_DIR>
18+
#
19+
# PLATFORM: Platform name, corresponding the one of the top-level directories
20+
# in solc-bin.
21+
# BASE_REF..TOP_REF: Commit range in the solc-bin repository to search for
22+
# modified binaries.
23+
# SOLC_BIN_DIR: Directory containing a checkout of the ethereum/solc-bin
24+
# repository with full history. Must be an absolute path.
25+
# SOLIDITY_DIR: Directory containing a checkout of the ethereum/solidity
26+
# repository with full history. Bytecode report will be generated using
27+
# scripts from the currently checked out revision. Must be an absolute path.
28+
#
29+
# Example:
30+
# <script name>.sh linux-amd64 gh-pages pr-branch "$PWD/solc-bin" "$PWD/solidity"
31+
# ------------------------------------------------------------------------------
32+
# This file is part of solidity.
33+
#
34+
# solidity is free software: you can redistribute it and/or modify
35+
# it under the terms of the GNU General Public License as published by
36+
# the Free Software Foundation, either version 3 of the License, or
37+
# (at your option) any later version.
38+
#
39+
# solidity is distributed in the hope that it will be useful,
40+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
41+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42+
# GNU General Public License for more details.
43+
#
44+
# You should have received a copy of the GNU General Public License
45+
# along with solidity. If not, see <http://www.gnu.org/licenses/>
46+
#
47+
# (c) 2020 solidity contributors.
48+
#------------------------------------------------------------------------------
49+
50+
# FIXME: Can't use set -u because the old Bash on macOS treats empty arrays as unbound variables
51+
set -eo pipefail
52+
53+
(( $# == 5 )) || { echo "ERROR: Not enough arguments."; exit 1; }
54+
55+
platform="$1"
56+
base_ref="$2"
57+
top_ref="$3"
58+
solc_bin_dir="$4"
59+
solidity_dir="$5"
60+
61+
report_dir="$PWD"
62+
tmp_dir=$(mktemp -d -t bytecode-reports-XXXXXX)
63+
solcjs_dir="$tmp_dir/solcjs"
64+
script_dir="$solidity_dir/scripts"
65+
66+
cd "$tmp_dir"
67+
68+
git clone https://github.com/ethereum/solc-js.git "$solcjs_dir"
69+
cd "$solcjs_dir"
70+
npm install
71+
rm soljson.js
72+
73+
cd "${solc_bin_dir}/${platform}/"
74+
echo "Commit range: ${base_ref}..${top_ref}"
75+
76+
modified_release_versions=$(
77+
git diff --name-only "${base_ref}" |
78+
sed -n -E 's/^[^\/]+\/(solc|soljson)-[0-9a-zA-Z-]+-v([0-9.]+)\+commit\.[0-9a-f]+(.[^.]+)?$/\2/p' |
79+
sort -V |
80+
uniq
81+
)
82+
echo "Release versions modified in the commit range:"
83+
echo "$modified_release_versions"
84+
85+
# NOTE: We want perform the check when the soljson-* files in bin/ and wasm/ are modified too
86+
# because in that case the symlinks in emscripten-wasm32/ and emscripten-asmjs/ might remain
87+
# unchanged but were're assuming that these directories are never directly used as a platform name.
88+
[[ $platform != bin && $platform != wasm ]] || { echo "Invalid platform name."; exit 1; }
89+
90+
platform_binaries="$(git ls-files "solc-${platform}-v*+commit.*" | sort -V)"
91+
92+
for binary_name in $platform_binaries; do
93+
solidity_version=$(echo "$binary_name" | sed -n -E 's/^solc-'"${platform}"'-v([0-9.]+)\+commit.+$/\1/p')
94+
95+
if echo "$modified_release_versions" | grep -x "$solidity_version"; then
96+
echo "Binary ${binary_name} (version ${solidity_version}) matches one of the modified versions."
97+
98+
work_dir="${tmp_dir}/${binary_name}"
99+
mkdir "$work_dir"
100+
cd "$work_dir"
101+
102+
# While bytecode scripts come from the latest compiler, the test files should come from
103+
# the Solidity version we're running them against to avoid errors due to breaking syntax changes.
104+
git clone --branch "v${solidity_version}" "$solidity_dir" "${work_dir}/solidity/"
105+
"${script_dir}/isolate_tests.py" "${work_dir}/solidity/test/"
106+
107+
if [[ $platform == emscripten-wasm32 ]] || [[ $platform == emscripten-asmjs ]]; then
108+
ln -sf "${solc_bin_dir}/${platform}/${binary_name}" "${solcjs_dir}/soljson.js"
109+
ln -s "${solcjs_dir}" solc-js
110+
cp "${script_dir}/bytecodecompare/prepare_report.js" prepare_report.js
111+
112+
# shellcheck disable=SC2035
113+
./prepare_report.js --strip-smt-pragmas *.sol > "${report_dir}/report-${binary_name}.txt"
114+
else
115+
yul_optimizer_flags=()
116+
if [[ $solidity_version == 0.6.0 ]] || [[ $solidity_version == 0.6.1 ]]; then
117+
yul_optimizer_flags+=(--force-no-optimize-yul)
118+
fi
119+
120+
"${script_dir}/bytecodecompare/prepare_report.py" "${solc_bin_dir}/${platform}/${binary_name}" \
121+
--interface cli \
122+
--smt-use strip-pragmas \
123+
--report-file "${report_dir}/report-${binary_name}.txt" \
124+
"${yul_optimizer_flags[@]}"
125+
fi
126+
127+
rm -r "${work_dir}/solidity/"
128+
else
129+
echo "Binary ${binary_name} (version ${solidity_version}) does not match any modified version. Skipping."
130+
fi
131+
done
132+
133+
echo rm -r "$tmp_dir"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env bash
2+
3+
# ------------------------------------------------------------------------------
4+
# Compares bytecode reports from multiple compiler versions and platforms to
5+
# determine if there are any differences.
6+
#
7+
# The script does not accept any arguments.
8+
#
9+
# The reports should be placed in subdirectories of the current working
10+
# directory and their names should follow one of the following patterns:
11+
#
12+
# report-solc-<platform>-v<solidity version>+commit.<commit hash>.txt
13+
# report-soljson-<platform>-v<solidity version>+commit.<commit hash>.js.txt
14+
#
15+
# Reports corresponding to the same version and commit hash are grouped together
16+
# and the script succeeds only if the files within each group are identical.
17+
# ------------------------------------------------------------------------------
18+
# This file is part of solidity.
19+
#
20+
# solidity is free software: you can redistribute it and/or modify
21+
# it under the terms of the GNU General Public License as published by
22+
# the Free Software Foundation, either version 3 of the License, or
23+
# (at your option) any later version.
24+
#
25+
# solidity is distributed in the hope that it will be useful,
26+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
27+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28+
# GNU General Public License for more details.
29+
#
30+
# You should have received a copy of the GNU General Public License
31+
# along with solidity. If not, see <http://www.gnu.org/licenses/>
32+
#
33+
# (c) 2020 solidity contributors.
34+
#------------------------------------------------------------------------------
35+
36+
set -euo pipefail
37+
38+
report_files="$(find . -type f -name 'report-*.txt')"
39+
[[ $report_files != "" ]] || { echo "No reports found in the working directory."; exit 0; }
40+
41+
echo "Available reports:"
42+
echo "$report_files"
43+
44+
versions_in_report_names=$(
45+
echo "$report_files" |
46+
sed -n -E 's/^\.\/[^\/]+\/report-(solc|soljson)-[0-9a-zA-Z-]+-v([0-9.]+\+commit\.[0-9a-f]+)(.[^.]+)?\.txt$/\2/p' |
47+
sort -V |
48+
uniq
49+
)
50+
51+
num_failed_comparisons=0
52+
for solidity_version_and_commit in $versions_in_report_names; do
53+
echo "Comparing reports for Solidity ${solidity_version_and_commit}:"
54+
mapfile -t report_files_for_version < <(
55+
echo "$report_files" |
56+
sed -n -E '/^\.\/[^\/]+\/report-(solc|soljson)-[0-9a-zA-Z-]+-v'"${solidity_version_and_commit//\+/\\+}"'+(.[^.]+)?\.txt$/p'
57+
)
58+
59+
diff --report-identical-files --brief --from-file "${report_files_for_version[@]}" || ((++num_failed_comparisons))
60+
echo
61+
done
62+
63+
(( num_failed_comparisons == 0 )) || { echo "Found bytecode differences in ${num_failed_comparisons} versions"; exit 1; }
64+
echo "No bytecode differences found."

0 commit comments

Comments
 (0)