Neutrinoで働くブロックチェーンエンジニアのブログ

渋谷の専門特化コワークNeutrinoに入居してブロックチェーンエンジニアとして働いています。元丸の内。(Neutrino運営企業とは直接関係ありません)

Ethereumのトランザクション(Message Call)について-Yellow Paper8章より

f:id:naomasabit:20180409114233j:plain

前回に続いて相変わらずEthereumのYellowPaperを読んで得た仕様をまとめます。

読んでいるYellowPaperのバージョンは「BYZANTIUM VERSION e94ebda - 2018-06-05」です。

今回は「8. Message Call」についてです。特に指定がない場合は、8章からの引用と考えてください。

前回の記事

www.blockchainengineer.tokyo

Ethereumの2種類のトランザクション

f:id:naomasabit:20180912222638j:plain

「4.2. The Transaction」より There are two types of transactions: those which result in message calls and those which result in the creation of new accounts with associated code (known informally as `contract creation').

Ethereumではトランザクションを2種類に分けています。

  • Contract Creation
  • Message Call

の2種類です。

Contract Creationとは

Contract Creationは、コントラクトアドレスを作成するトランザクション

すなわち、スマートコントラクトをアドレスに乗せてEthereumにデプロイするトランザクションのことです。

デプロイ時にはバイトコードを乗せたトランザクションを発行することでコントラクトアドレスが生成されます。

Message Callとは

Message Call(メッセージコール)は、送金やコントラクトのコード、関数などを呼び出すときに使われるトランザクションです。

コントラクトを作成するもの以外全てと考えた方がわかりやすいかもしれません。Message Callは、形式的に言えば、イーサリアムのWorld Stateを変更する結果をもたらします。

World Stateとは、Ethereum世界全体におけるState(状態)を表し、各々のアカウントのもつ状態(Account State)の集合体です。

記号としては、

δ : World State

δ[a] : Account State

で定義されています。

Account Stateは以下4項目で、各アカウント(アドレス)の状態は以下4つで定義されます。

一番重要かつ明快なのは残高で、例えばMessage CallによってETHを送信すれば、送金者、着金者のbalanceが変化してAccount Stateが変化することになります。

「Message Call」という呼び名は、おそらくEthereum全体を一つのコンピュータとみなした時に、各アカウントがオブジェクト、そのオブジェクト間の通信がトランザクションであり、コンピュータの既存概念の「メッセージ」と考えたからだと思います。

Message Callを実行するにあたって必要なパラメータ

In the case of executing a message call, several parameters are required: sender (s), transaction originator (o), recipient (r), the account whose code is to be executed (c, usually the same as recipient), available gas (g), value (v) and gas price (p) together with an arbitrary length byte array, d, the input data of the call, the present depth of the message-call/contract-creation stack (e) and finally the permission to make modifications to the state (w).

Message Callを実行するにあたっては、以下パラメータが必要になると示されています。

名前(略記号) 意味合い
sender(s) トランザクション送信アドレス
transaction originator (o) トランザクション作成アドレス
recipient (r) トランザクション受信アドレス
the account whose code is to be executed (c, usually the same as recipient) コードが実行されるアドレス(通常は受信者)
available gas (g) 利用可能なガス
value (v) 送金額
gas price (p) ガス価格
the input data of the call (d) メッセージコールに利用するためのインプットデータ
the present depth of the message-call/contract-creation stack メッセージコール、コントラクト作成スタックの現在の深さ
(おそらく、再帰的に何度呼び出されているか=深さを指している)
the permission to make modifications to the state (w) stateに変更を与える権限

Message Call実行結果の内容について

Aside from evaluating to a new state and transaction substate, message calls also have an extra component the output data denoted by the byte array o. This is ignored when executing transactions, however message calls can be initiated due to VM-code execution and in this case this information is used.

Message Callは、stateやトランザクションのsubstateに変更を加えることとは別に、バイト配列Oで示されるアウトプットデータを得ます。

トランザクションを実行する最初は使われませんが、VMコードの実行時に、返り値を使うなどのケースでアウトプットデータが使用される、と言っています。(プログラミング経験者からすると当然のことが書かれています)

f:id:naomasabit:20180912222853p:plain

実行結果は、上記(98) の式によると

  • δ' 変更された後のWorld State
  • g' 実行後のgasの値(残り)
  • A トランザクションのsubstate(Yellow Paper「6.1. Substate.」に定義あり)
  • z 実行結果(成功・失敗)

を含みます。

Message Callが失敗した場合の例外処理について

The account's associated code (identified as the fragment whose Keccak hash is [c]c) is executed according to the execution model (see section 9). Just as with contract creation, if the execution halts in an exceptional fashion (i.e. due to an exhausted gas supply, stack underflow, invalid jump destination or invalid instruction), then no gas is refunded to the caller and the state is reverted to the point immediately prior to balance transfer (i.e. ).

コントラクト作成(contract creation)で失敗した場合と同様に、例外が発生して実行が止まった場合、送信者へのガスの払い戻しは行われません。Message Callによって変更を加えようとしていたstateは送信前に戻されます。

実行が失敗するケースには指定ガスの超過、スタックアンダーフロー、不正なJUMP先の指定、不正な命令などが例示されています。

precompiled contractという特殊な実行方法

f:id:naomasabit:20180912224322j:plain

As can be seen, there are eight exceptions to the usage of the general execution framework for evaluation of the message call: these are eight so-called `precompiled' contracts, meant as a preliminary piece of architecture that may later become native extensions.

message callには、8つの特殊な、例外的とも言える実行手法があります。

  1. 楕円曲線暗号で公開鍵を復元する機能 (ecrecover関数と呼ばれるもの)
  2. SHA256ハッシュ
  3. RIPEMD160ハッシュ
  4. データコピー(identity 関数)
  5. 任意の精度における冪剰余
  6. 楕円曲線暗号の値を加算
  7. 楕円曲線暗号の値を掛け算
  8. 楕円曲線暗号のペアをチェック

これらはprecompiled contractと呼ばれます。

precompiled contractについては、Gunosyブロックチェーンブログの記事から引用させていただきます。

暗号学的で非常に複雑な処理は、貧弱なEVM1のオペコードに直して実行したくはありません。 そこで、処理を高速化するべくクライアントの実装の中に含めて事前に機械語コンパイルしておき、特定のハードコーディングされたアドレス(ex:0x0000000000000000000000000000000000000001)のコントラクトが呼ばれた場合は、ブロックチェーンからではなくクライアントに実装されたロジックを実行していました。

より

説明は上記ブログの通りなのですが、計算処理をEVMでなく外部で処理して実行している事をMessage Callの中でも特殊な処理としてあげています。

クライアント実装であるgo-ethereumでPrecompiled Contractを呼び出している処理は以下になります。これらの処理は実際にはクライアント側、go-ethereum上で実行されます。

var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
    common.BytesToAddress([]byte{1}): &ecrecover{},
    common.BytesToAddress([]byte{2}): &sha256hash{},
    common.BytesToAddress([]byte{3}): &ripemd160hash{},
    common.BytesToAddress([]byte{4}): &dataCopy{},
    common.BytesToAddress([]byte{5}): &bigModExp{},
    common.BytesToAddress([]byte{6}): &bn256Add{},
    common.BytesToAddress([]byte{7}): &bn256ScalarMul{},
    common.BytesToAddress([]byte{8}): &bn256Pairing{},
}

引用元のコード

go-ethereum/contracts.go at master · ethereum/go-ethereum · GitHub

Byzantiumハードフォークを経て、1~4までのprecompiled contractに加えて5~8が実装されることになりました。

これらのprecompiled contractの詳細な定義についてもYellow PaperのAppendix E.に掲載されています。