コントリビューティング
貢献はいつでも歓迎です。 Solidityに貢献するための選択肢はたくさんあります。
特に、以下の領域でのサポートに感謝します。
イシューの報告。
SolidityのGitHubイシュー (特に「 good first issue 」タグの付いた、外部の貢献者のための入門的なイシュー)の修正と対応。
ドキュメントの改善。
新しい言語のドキュメントの 翻訳 。
他のユーザーからの StackExchange や Solidity Gitter Chat での質問への返答。
Solidityフォーラム で言語の変更や新機能を提案やフィードバックの提供による言語設計プロセスへの関与。
まずは ソースからのビルド を使って、Solidityのコンポーネントやビルドプロセスに慣れてみてください。 また、Solidityでのスマートコントラクトの書き方を熟知することも有効でしょう。
このプロジェクトは Contributor Code of Conduct 付きで公開されていることにご注意ください。 イシュー、プルリクエスト、Gitterチャンネルなど、このプロジェクトに参加することで、その条件を守ることに同意したことになります。
チームコール
議論したいイシューやプルリクエストがある場合や、チームやコントリビューターが取り組んでいることを聞きたい場合は、パブリックなチームコールに参加できます。
毎週水曜日の午後3時(CET/CEST)から。
コールは Jitsi で行われます。
イシューの報告方法
問題を報告するには、 GitHubイシュートラッカー を利用してください。 報告の際には、以下の内容をお知らせください。
Solidityのバージョン。
ソースコード(必要に応じて)。
オペレーティングシステム。
イシューを再現するための手順。
実際の挙動と期待される挙動の比較。
イシューの原因となったソースコードを最小限に減らすことは、常に非常に役に立ち、時には誤解を解くことにもなります。
言語設計に関する技術的な議論については、 Solidity forum への投稿が正しい場所です( Solidityの言語設計 を参照してください)。
プルリクエストのワークフロー
貢献するためには、 develop
ブランチをフォークして、そこで変更を加えてください。
コミットメッセージには、変更した内容に加えて、変更した理由を詳しく書いてください(小さな変更の場合を除く)。
フォーク後に develop
からの変更を取り込む必要がある場合(たとえば、潜在的なマージコンフリクトを解決するため)、 git merge
の使用を避け、代わりに git rebase
でブランチを作成してください。
そうすることで、あなたの変更をより簡単に確認できます。
また、新機能を書いている場合は、 test/
の下に適切なテストケースを追加してください(下記を参照してください)。
ただし、より大きな変更を行う場合は、まず Solidity Development Gitter チャンネル (前述のものとは異なり、こちらは言語の使い方ではなく、コンパイラや言語の開発に重点を置いています)に相談してください。
新機能やバグフィックスは、 Changelog.md
ファイルに追加してください。
該当する場合は、過去のエントリーのスタイルに従ってください。
最後に、このプロジェクトの コーディングスタイル を尊重するようにしてください。 また、CIテストを行っているとはいえ、プルリクエストを提出する前にコードをテストし、ローカルにビルドされることを確認してください。
プルリクエストを提出する前に、私たちの レビューチェックリスト に目を通すことを強くお勧めします。 私たちはすべてのPRを徹底的にレビューし、あなたが正しい結果を得られるようサポートしますが、簡単に回避できる多くの一般的な問題があり、レビューがよりスムーズに行えるようになります。
ご協力ありがとうございます!
コンパイラーテストの実行
事前準備
すべてのコンパイラテストを実行するために、いくつかの依存関係( evmone と libz3 )をオプションでインストールできます。
macOSでは、一部のテストスクリプトでGNU coreutilsがインストールされていることが前提となっています。
インストールするにはHomebrewを使うのが最も簡単です: brew install coreutils
。
Windowsシステムでは、シンボリックリンクを作成する権限を持っていることを確認してください、さもなければいくつかのテストが失敗するかもしれません。 管理者がその権限を持つべきですが、 他のユーザーにその権限を与えること や、 開発者モードを有効にする ことも可能です。
テストの実行
Solidityには様々なタイプのテストがあり、そのほとんどが Boost C++ Test Framework アプリケーション soltest
にバンドルされています。
ほとんどの変更には、 build/test/soltest
またはそのラッパー scripts/soltest.sh
を実行すれば十分です。
./scripts/tests.sh
スクリプトは、 Boost C++ Test Framework アプリケーション soltest
(またはそのラッパー scripts/soltest.sh
)にバンドルされているものや、コマンドラインテスト、コンパイルテストなど、ほとんどのSolidityテストを自動的に実行します。
テストシステムは、セマンティックテストを実行するための evmone の場所を自動的に発見しようとします。
evmone
ライブラリは、現在の作業ディレクトリ、その親、またはその親の親に対する deps
または deps/lib
ディレクトリに配置されている必要があります。
また、環境変数 ETH_EVMONE
を使って evmone
共有オブジェクトの場所を明示的に指定することもできます。
evmone
は主にセマンティックテストとガステストを実行するために必要です。
インストールされていない場合は、 scripts/soltest.sh
に --no-semantic-tests
フラグを渡すことで、これらのテストをスキップできます。
evmone
ライブラリと hera
ライブラリは、どちらもファイル名の拡張子が、Linuxでは .so
、Windowsシステムでは .dll
、macOSでは .dylib
になるようにしてください。
SMTテストを実行するためには、 libz3
ライブラリがインストールされており、コンパイラのconfigure段階で cmake
が位置を特定できる必要があります。
libz3
ライブラリがシステムにインストールされていない場合は、 ./scripts/tests.sh
を実行する前に SMT_FLAGS=--no-smt
をエクスポートしてSMTテストを無効にするか、 ./scripts/soltest.sh --no-smt
を実行する必要があります。
これらのテストは libsolidity/smtCheckerTests
と libsolidity/smtCheckerTestsJSON
です。
注釈
Soltestで実行されたすべてのユニットテストのリストを取得するには、 ./build/test/soltest --list_content=HRF
を実行してください。
より迅速な結果を得るために、一部のテストや特定のテストを実行できます。
テストのサブセットを実行するには、 ./scripts/soltest.sh -t TestSuite/TestName``のようにフィルターを使うことができます。
``TestName
にはワイルドカード *
を指定できます。
あるいは、例えば、yul disambiguatorのすべてのテストを実行するには、次のようにします。
./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-smt
です。
./build/test/soltest --help
には、利用可能なすべてのオプションに関する広範なヘルプがあります。
特に、以下のオプションを参考にしてください。
show_progress (-p): テストの進行状態を表示します。
run_test (-t) : 特定のテストケースを実行します。
report-level (-r): より詳細な報告をします。
注釈
Windows環境で、上記の基本セットをlibz3なしで実行したい方は、次のようにしてください。
Git Bashを使っている場合、 ./build/test/Release/soltest.exe -- --no-smt
を実行してください。
プレーンなコマンドプロンプトで実行する場合、 .\build\test\Release\soltest.exe -- --no-smt
を実行してください。
GDBを使ってデバッグしたい場合は、「通常」とは異なる方法でビルドするようにしてください。
例えば、 build
フォルダで以下のコマンドを実行します。
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
これにより、 --debug
フラグを使ってテストをデバッグする際に、ブレークやプリントが可能な関数や変数にアクセスできるようにシンボルが作成されます。
CIは、Emscriptenターゲットのコンパイルを必要とする追加のテスト( solc-js
やサードパーティのSolidityフレームワークのテストなど)を実行します。
構文テストの作成と実行
構文テストは、コンパイラが無効なコードに対して正しいエラーメッセージを生成し、有効なコードを適切に受け入れるかどうかをチェックします。
これらのテストは tests/libsolidity/syntaxTests
フォルダー内の個々のファイルに格納されます。
これらのファイルには、それぞれのテストで期待される結果を記載した注釈を含める必要があります。
テストスイートは、これらのファイルをコンパイルし、期待される結果に対してチェックします。
例えば、次のようなものです。
./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol
contract test {
uint256 variable;
uint128 variable;
}
// ----
// DeclarationError: (36-52): Identifier already declared.
構文テストは、少なくともテスト対象のコントラクトそのものと、それに続くセパレータ // ----
を含んでいなければなりません。
セパレータに続くコメントは、予想されるコンパイラのエラーや警告を説明するために使用されます。
数字の範囲は、エラーが発生したソースの場所を示します。
もし、エラーや警告を出さずにコントラクトをコンパイルしたい場合は、セパレータとそれに続くコメントを省くことができます。
上の例では、状態変数 variable
が2回宣言されていますが、これは許されません。
この結果、識別子がすでに宣言されているという DeclarationError
が表示されます。
これらのテストには isoltest
ツールが使用されており、 ./build/test/tools/
で見つけることができます。
これは対話型のツールで、好みのテキストエディタを使って失敗したコントラクトを編集できます。
variable
の2番目の宣言を削除することで、このテストを破ってみましょう。
contract test {
uint256 variable;
}
// ----
// DeclarationError: (36-52): Identifier already declared.
./build/test/tools/isoltest
を再度実行すると、テストが失敗します。
syntaxTests/double_stateVariable_declaration.sol: FAIL
Contract:
contract test {
uint256 variable;
}
Expected result:
DeclarationError: (36-52): Identifier already declared.
Obtained result:
Success
isoltest
は、期待される結果を得られた結果の横に表示し、また、現在のコントラクトファイルを編集、更新、スキップしたり、アプリケーションを終了する方法を提供します。
テストを失敗させるためのいくつかのオプションがあります。
edit
:isoltest
は、コントラクト内容を調整できるように、エディタでコントラクト内容を開こうとします。isoltest --editor /path/to/editor
のようにコマンドラインで指定されたエディタを使用するか、EDITOR
のように環境変数で指定されたエディタを使用するか、/usr/bin/editor
だけを使用するか(順不同)。
update
: テスト中のコントラクトに対する期待値を更新。 これは、満たされていない期待値を削除し、満たされていない期待値を追加することで、アノテーションを更新します。 その後、テストが再度実行されます。
skip
: この特定のテストの実行をスキップします。
quit
:isoltest
を終了します。
これらのオプションは、テストプロセス全体を停止する quit
を除いて、すべて現在のコントラクトに適用されます。
上のテストを自動的に更新すると、次のように変更されます。
contract test {
uint256 variable;
}
// ----
そして、テストを再実行します。 これで合格です。
Re-running test case...
syntaxTests/double_stateVariable_declaration.sol: OK
注釈
コントラクトファイルの名前には、 double_variable_declaration.sol
など、テストする内容を説明するものを選んでください。
継承やクロスコントラクトコールをテストする場合を除き、1つのファイルに複数のコントラクトを入れないでください。
各ファイルは、新機能の1つの側面をテストする必要があります。
コマンドラインテスト
エンドツーエンドのコマンドラインテストスイートは、様々なシナリオにおけるコンパイラバイナリ全体の動作をチェックします。
これらのテストは test/cmdlineTests/ にサブディレクトリごとに1つずつあり、 cmdlineTests.sh
スクリプトを使って実行できます。
デフォルトでは、スクリプトは利用可能なすべてのテストを実行します。
また、1つ以上の ファイル名パターン を指定することもでき、その場合は少なくとも1つのパターンにマッチするテストのみが実行されます。
また、特定のパターンの前に --exclude
をつけることで、そのパターンにマッチするファイルを除外することもできます。
デフォルトでは、スクリプトは solc
バイナリが作業コピーの build/
サブディレクトリにあると仮定します。
コンパイラをソースツリーの外でビルドする場合は、 SOLIDITY_BUILD_DIR
環境変数を使ってビルドディレクトリを別の場所に指定できます。
例:
export SOLIDITY_BUILD_DIR=~/solidity/build/
test/cmdlineTests.sh "standard_*" "*_yul_*" --exclude "standard_yul_*"
上記のコマンドは test/cmdlineTests/standard_
で始まるディレクトリと test/cmdlineTests/
のサブディレクトリで、名前のどこかに _yul_
が含まれるテストを実行しますが、名前が standard_yul_
で始まるテストは実行されません。
また、ホームディレクトリにある solidity/build/solc/solc
ファイルがコンパイラのバイナリであると仮定されます(Windows を使用している場合は、 solidity/build/solc/Release/solc.exe
を使用します)。
コマンドラインテストにはいくつかの種類があります。
標準JSONテスト: 少なくとも
input.json
ファイルが含まれます。 一般的に含まれているものは以下の通りです。input.json
: コマンドラインで--standard-json
オプションに渡す入力ファイル。output.json
: 標準JSON出力ファイル。args
:solc
に渡す追加のコマンドライン引数。
CLIテスト: 少なくとも
input.*
ファイルが含まれます(input.json
以外). 一般的に含まれているものは以下の通りです。input.*
: コマンドラインでsolc
に与えられる単一の入力ファイル。 通常はinput.sol
またはinput.yul
。args
:solc
に渡される追加のコマンドライン引数。stdin
: 標準入力からsolc
に渡す内容。output
: 期待される標準出力の内容。err
: 期待される標準エラー出力の内容。exit
: 期待される終了コード。省略された場合は0。
スクリプトテスト:
test.*
ファイルが含まれます。 一般的に含まれているものは以下の通りです。test.*
: 単一のスクリプトで、通常はtest.sh
またはtest.py
。 スクリプトは実行可能でなければなりません。
AFLによるファザーの実行
ファジングとは、多かれ少なかれランダムな入力に対してプログラムを実行し、例外的な実行状態(セグメンテーションフォールトや例外など)を見つける技術です。
最近のFuzzerは賢く、入力の内部で有向検索を行います。
私たちは solfuzzer
と呼ばれる特殊なバイナリを持っています。
solfuzzer
はソースコードを入力として受け取り、内部のコンパイラエラーやセグメンテーションフォールトなどに遭遇するたびに失敗しますが、例えばコードにエラーが含まれている場合は失敗しません。
このようにして、ファジングツールはコンパイラの内部問題を見つけることができます。
ファジングには主に AFL を使用しています。
AFLパッケージをリポジトリ(afl, afl-clang)からダウンロードしてインストールするか、手動でビルドする必要があります。
次に、AFLをコンパイラとしてSolidity(または solfuzzer
バイナリのみ)をビルドします。
cd build
# if needed
make clean
cmake .. -DCMAKE_C_COMPILER=path/to/afl-gcc -DCMAKE_CXX_COMPILER=path/to/afl-g++
make solfuzzer
この段階では、以下のようなメッセージが表示されます。
Scanning dependencies of target solfuzzer
[ 98%] Building CXX object test/tools/CMakeFiles/solfuzzer.dir/fuzzer.cpp.o
afl-cc 2.52b by <lcamtuf@google.com>
afl-as 2.52b by <lcamtuf@google.com>
[+] Instrumented 1949 locations (64-bit, non-hardened mode, ratio 100%).
[100%] Linking CXX executable solfuzzer
インストルメンテーションメッセージが表示されない場合は、AFLのclangバイナリを指すcmakeフラグを切り替えてみてください。
# if previously failed
make clean
cmake .. -DCMAKE_C_COMPILER=path/to/afl-clang -DCMAKE_CXX_COMPILER=path/to/afl-clang++
make solfuzzer
そうでない場合は、実行時に「binary is not instrumented」というエラーでファザーが停止します。
afl-fuzz 2.52b by <lcamtuf@google.com>
... (truncated messages)
[*] Validating target binary...
[-] Looks like the target binary is not instrumented! The fuzzer depends on
compile-time instrumentation to isolate interesting test cases while
mutating the input data. For more information, and for tips on how to
instrument binaries, please see /usr/share/doc/afl-doc/docs/README.
When source code is not available, you may be able to leverage QEMU
mode support. Consult the README for tips on how to enable this.
(It is also possible to use afl-fuzz as a traditional, "dumb" fuzzer.
For that, you can use the -n option - but expect much worse results.)
[-] PROGRAM ABORT : No instrumentation detected
Location : check_binary(), afl-fuzz.c:6920
次に、いくつかのサンプルソースファイルが必要です。 これにより、ファザーがエラーを見つけるのが非常に簡単になります。 構文テストからいくつかのファイルをコピーするか、ドキュメントや他のテストからテストファイルを抽出できます。
mkdir /tmp/test_cases
cd /tmp/test_cases
# extract from tests:
path/to/solidity/scripts/isolate_tests.py path/to/solidity/test/libsolidity/SolidityEndToEndTest.cpp
# extract from documentation:
path/to/solidity/scripts/isolate_tests.py path/to/solidity/docs
AFLのドキュメントでは、コーパス(最初の入力ファイル)はあまり大きくしない方が良いとされています。
ファイル自体の大きさは1kB以下で、1つの機能に対して入力ファイルは多くても1つなので、少ない数から始めた方が良いでしょう。
また、 afl-cmin
というツールがあり、バイナリの挙動が似ている入力ファイルをトリミングできます。
ここで、ファザーを実行します( -m
ではメモリサイズを60MBに拡張しています)。
afl-fuzz -m 60 -i /tmp/test_cases -o /tmp/fuzzer_reports -- /path/to/solfuzzer
ファザーは、 /tmp/fuzzer_reports
の失敗につながるソースファイルを作成します。
多くの場合、同じエラーを発生させる多くの類似したソースファイルを見つけます。
ツール scripts/uniqueErrors.sh
を使って、固有のエラーをフィルタリングできます。
Whiskers
Whiskers は、 Mustache に似た文字列テンプレートシステムです。 コンパイラは、コードの可読性、ひいては保守性や検証性を高めるために、さまざまな場所でこのシステムを使用しています。
この構文は、Mustacheとは大幅に異なります。
テンプレートマーカー {{
と }}
は、解析を助け、 Yul との衝突を避けるために、 <
と >
に置き換えられています(シンボル <
と >
はインラインアセンブリでは無効であり、 {
と }
はブロックの区切りに使用されます)。
もう1つの制限は、リストは1つの深さまでしか解決されず、再帰的にはならないことです。
これは将来変更される可能性があります。
大まかな仕様は以下の通りです。
<name>
が出現すると、与えられた変数 name
の文字列値で置き換えられます。
このとき、エスケープや繰り返しの置き換えは行われません。
ある領域は <#name>...</name>
で区切ることができます。
領域は、テンプレートシステムに供給された変数セットの数だけ、その内容を連結したものに置き換えられ、その都度、 <inner>
項目をそれぞれの値で置き換えます。
トップレベルの変数は、このような領域内で使用することもできます。
<?name>...<!name>...</name>
形式の条件式もあります。
ここでは、ブーリアンパラメータ name
の値に応じて、テンプレートの置換が最初のセグメントまたは2番目のセグメントで再帰的に続けられます。
<?+name>...<!+name>...</+name>
を使用する場合は、文字列パラメータ name
が空でないかどうかをチェックします。
ドキュメンテーションのスタイルガイド
次のセクションでは、Solidityへのドキュメント提供に特化したスタイルの推奨事項を紹介します。
英語
プロジェクト名やブランド名を使用する場合を除き、国際英語を使用してください。 ローカルのスラングや参考文献の使用を極力控え、誰が読んでも分かりやすい言葉遣いを心がけてください。 以下は参考資料です。
見出しのタイトルケース
見出しには タイトルケース を使用します。 つまり、タイトルの主要な単語はすべて大文字にしますが、冠詞、接続詞、前置詞はタイトルの最初でない限り、大文字にしません。
例えば、次のようなものはすべて正しいです。
Title Case for Headings
For Headings Use Title Case
Local and State Variable Names
Order of Layout
短縮形の展開
単語では短縮形を利用しないでください。 例えば、
「Don't」ではなく「Do not」。
「Can't」ではなく「Can not」。
能動態と受動態
チュートリアル形式のドキュメントでは、誰が、何がタスクを実行しているのかを読者が理解しやすいように、能動態(アクティブボイス)を推奨します。 しかし、Solidityのドキュメントは、チュートリアルとリファレンスコンテンツが混在しているため、受動態(パッシブボイス)の方が適している場合もあります。
要約すると
例えば、Ethereum VMの言語定義や内部構造などの技術的な参照には、受動態を使用します。
Solidityのある側面を適用するための推奨事項を説明する際には、能動態を使用します。
例えば、以下はSolidityの側面を指定しているため、受動態になっています。
Functions can be declared
pure
in which case they promise not to read from or modify the state.
例えば、以下はSolidityのアプリケーションについて説明しているので、能動態になっています。
When invoking the compiler, you can specify how to discover the first element of a path, and also path prefix remappings.
一般的用語
「function parameters」と「return variables」であり、input parametersとoutput parametersではありません。
コードの例
CIプロセスでは、PRを作成する際に ./test/cmdlineTests.sh
スクリプトを使用して pragma solidity
、 contract
、 library
、 interface
で始まるコードブロック形式のコード例をすべてテストします。
新しいコード例を追加する場合は、PRを作成する前にそのコード例が動作し、テストに合格することを確認してください。
すべてのコード例は、コントラクトコードが有効な最大の範囲をカバーする pragma
バージョンで始まるようにします。
例えば、 pragma solidity >=0.4.0 <0.9.0;
などとしてください。
ドキュメントのテストの実行
ドキュメントに必要な依存関係をインストールし、リンク切れや構文の問題などの問題をチェックする ./docs/docs.sh
を実行することで、あなたの貢献が私たちのドキュメントテストに合格することを確認してください。
Solidityの言語設計
言語設計のプロセスに積極的に参加し、Solidityの将来に関するアイデアを共有するには、 Solidityフォーラム に参加してください。
Solidityフォーラムは、新しい言語機能やその実装のアイデアの初期段階や、既存の機能の修正を提案し、議論する場として機能しています。
提案が具体的になれば、その実現に向けて SolidityのGitHubリポジトリ でもイシューという形で議論されます。
フォーラムやイシューの議論に加えて、定期的に言語設計ディスカッションコールを開催し、特定のトピックや課題、機能の実装について詳細に議論しています。 これらのコールへの招待状は、フォーラムを通じて共有されます。
また、フィードバックアンケートなど、言語設計に関連したコンテンツをフォーラムで共有しています。
新機能の実装についてチームの状況を知りたい場合は、 SolidityのGithubプロジェクト で実装状況を確認できます。 デザインバックログに登録されている問題は、さらに詳細な仕様が必要なため、言語デザインコールまたは通常のチームコールで議論されます。 デフォルトのブランチ( develop )から breakingブランチ に変更することで、次のブレーキングリリースに向けた変更点を確認できます。
その場限りのケースや質問については、Solidityコンパイラや言語開発に関する会話のための専用チャットルームである Solidity-dev Gitter チャンネル を通じて連絡を取ることができます。
言語設計のプロセスをより協力的で透明性の高いものに改善するために、みなさんの意見をお聞かせください。