#3.1.2 ブロックチェーンの基本
マイニング・ハッシュ・楕円曲線暗号・P2Pネットワークといったもっとも複雑な部分がブロックチェーンの特徴を提供してくれる。
##[トランザクション]
ブロックチェーンはグローバルに共有されたトランザクションデータベースである。誰でもネットワークに参加することで、データベースを読み込める。他の人に受け入れられるトランザクションを生成すれば、データベースの一部を変更できる(全ては無理)。一度承認されたトランザクションの書き換えはできない。トランザクションが送信者によって暗号学的に署名をされる。これはこの記録に関する外部からの修正しようとするアクセスからトランザクションを保護してくれる。鍵を持つ者だけが、この電子通貨を移転させられる。
##[ブロック]
2つブロックが存在した時、最初に受け入れられるブロックにP2Pにおいて客観性があるわけではない。グローバルに受け入れられるトランザクションの順番は衝突を解決して、選択されている。時間的に線型な順番でブロックは配置されていく。これが"ブロックチェーン"の由来だ。イーサリアムは17秒ごとにブロックが追加される。マイニングという順番選択の仕組みにおいてたまに、チェーンの先端からブロックが戻される時がある。より多くブロックを積み上げていくと、ブロックが戻される可能性は低くなる。長く待つとその可能性は低くなる。
###注意
トランザクションは必ず次あるいはその先のブロックに加えられるわけではない。どのブロックにトランんザクションを含めるかは、トランザクションの送信者ではなく、マイナー次第だから。
#3.1.3 EVM
##[概要]
EVMはイーサリアム上でスマートコントラクトの為のプログラム実行環境。これはsandbox(隠されている、保護されている)だけではなく、実際は完全に隔離されている。EVM内でコードを実行することが、他のネットワーク、ファイルシステム、その他のプロセスへのアクセスする方法を持たない。スマートコントラクトでさえ、他のコントラクトへのアクセスは制限されている。
##[アカウント]
アカウントは2つある。秘密鍵によって人間に制御される外部アカウント(Externaly owned Account)。アドレスは公開鍵からできる。一緒に保存されたコードによって制御されるコントラクトアカウント。アドレスは生成者のアドレス、そのアドレスから送られたトランザクションの数つまりnonceによって、コントラクト作成時に決まる。2つのアカウントはコードを保存しているかどうかに関わらず、EVM内で同等に扱われる。全てのアカウントはstorageと呼ばれる、256ビットの文字列からなる永続的なkey-Valueのmappingをもっている。またether建のbalance(残高)ももっている。
##[トランザクション]
トランザクションはpayload(データ本体)と呼ばれるバイナリーコードとetherを含むことができる。もし目標のアカウントがコードを含んでいれば、そのコードは実行され、payloadはinput dataとして、提供される。もしそのトランザクションがsetされていない(トランザクションがrecipientを持っていないか、recipientがnullの時)そのトランザクションは新しいコントラクトを生成する。そのコントラクトを生成したトランザクションのpayloadはEVMバイトコードに翻訳され、実行される。この実行されて、生成されたoutputは永続的にコントラクトのコードとして保存される。コントラクトを生成する為には、実際のコントラクトのコードを送る必要はなく、実行された時にそのコードを返すコードを送れば良い。
###注意
コントラクトが生成されている時、コードはまだ空である。なのでコンストラクラーが実行を終えるまで、生成中のコントラクトをコールすべきではない。
##[Gas]
生成時、トランザクションは一定の額のガスを伴って、chargeされる。その目的はトランザクション実行時にその実行への支払いに必要な動作分の額に制限すること。EVMはそのトランザクションを実行すると、そのトランザクションのガスはルールに従って、徐々に減少していく。gasがなくなるとgas欠の例外が投げられると、現在のコールした枠組み内での変更された状態を全て元に戻す。
##[Storage,MemoryそしてStack]
EVMはdata-storage、memory、stackという3つの領域をもつ。
###(Storage)
各アカウントはstorageというデータ領域をもつ。これは関数呼び出しとトランザクションの行われる間は永続的だ。Storageは256bitのkey-valueのmappingを保存する。あるコントラクト内のstorageを数え上げるのは不可能だ。比較的storageを読み上げるのは、費用がかかるし、その修正や初期化はもっとかかる。永続性のあるstorageへの保存は最小限にするべき。コントラクトに必要なものだけで良い。派生する計算やcaching、集計はコントラクトの外部に保存するべき。コントラクトはその外部にあるいかなるデータへも読み書きはできない。
###(memory)
コントラクトが各メッセージの呼び出しごとに新しくクリアされたインスタンをもつ。その中にあるのがmemoryと呼ばれるデータ領域。memoryは線形でバイトレベルで扱われる。読み込みは256bitまでに制限されている。書き込みは8~256ビットの幅がある。memoryは以前触れられていないワード内の任意のオフセットに書き込みや読み込みといったアクセスをする時、256ビットの文字によって拡張される。拡張時にガス費用が支払われなければならない。
###(stack)
EVMはregister machineではなく、stack machineである。stackと呼ばれるデータ領域で全ての計算が実行される。それは最大で1024エレメントのサイズと256ビットの文字数を持つ。stackへのアクセスは以下の方法に制限されている。
(1)stackの一番上の16要素の1つをコピーすることやstackの一番上の16要素の1つをそれよりしたの中の1つと交換できる。
(2)stackから2つ要素を取り出して、操作を加え、その結果をstackにpushすることができる。
(3)そのstackへより深いアクセスを得る為に、stackの要素をstorageやmemoryに移すことができる。ただし一番上のstackを最初に取り除かないと、その下の任意の要素(stack)にアクセスすることはできない。
##[Instruction Set(指示書)]
指示書は、consensus problemsを引き起こすような不正確または不一致な実装を避ける為に、最小化されている。すべての命令は、基本データ型、256ビットワード、またはメモリスライスに対して、動作する。条件付きと無条件のジャンプが可能。加えて、コントラクトはブロックナンバーやタイムスタンプといった現在のブロックに関係する性質にアクセスすることができる。
##[message call]
コントラクトはmessage callという手段で、他のコントラクトを呼び出したり、EOAにetherを送信することができる。message call はsource,target,data payload,ether,gas,データを返すという点で、トランザクションに似ている。実際全てのトランザクションは次にまた新しいメッセージコールを作成できるというトップレベルのメッセージコールから構成されている。
コントラクトは、残りのガスがいくら内部のメッセージコールとともに送信されるべきか、残りのガスがいくら維持されるべきかを決められる。内部呼び出し(またはその他の例外)でガス不足の例外が発生した場合は、スタックに設定されたエラー値によって通知されます。この場合、コールとともに送信されたガスだけ、使い果たされる。呼び出し元のコントラクトはマニュアル的に"bubble up"という例外を投げる。
呼ばれるコントラクトはmemoryに新しくクリアされたインスタンスを受け取り、calldataと呼ばれる隔離された領域に提供されるcall payloadにアクセスできる。message callの実行が終わるとそれは呼び出し元のコントラクトによって事前に割り当てられた呼び出し元のmemoryの場所に保存されるデータを返す。
呼び出しは1024の深さまでに制限されている。なぜならそれより複雑な操作は再帰呼び出しよりループが優先されることになるため。
##[Delegatecall/ Callcode and Libraries]
Delegatecallとは目標のアドレスのコードが呼び出し元のコントラクト内で実行され、msg.sender(その関数を実行したアカウントのアドレス型の値)とmsg.value(その関数を実行したアカウントが保持する値)が変化しないという点を除いて、メッセージ呼び出しと同じな、特殊なメッセージ呼び出し。コントラクトは実行時と異なるアドレスから動的にロードできる。storage,現在のアドレスとbalanceは依然として呼び出し元のコントラクトを参照する。コードのみが呼び出されたアドレスから取得される。ライブラリ機能はこれにより実現される。複雑なデータ構造を実装するようなコントラクトのstorageにライブラリーコードは再利用して適用することができる。
##[logs(履歴)]
ブロックレベルに紐ずけることができる、特別なインデックスデータストラクチャーにデータを保存することができる。logsと呼ばれるこの機能はeventsを実装するのに用いられる。ログが生成された後にコントラクトはログのデータにアクセスすることができない。しかし効率的にブロックチェーンの外部からlogのデータにアクセスすることはできる。bloom filtersにlog dataの一部は保存されている為、効率的かつ暗号学的にセキュアな方法でそのデータにアクセスすることができる。light clientもこれらのlogを見つけられる。
##[create]
コントラクトは特別なopcodeを用いて他のコントラクトを生成することができる。create callsと普通のmessage callsの違いは、payload dataを実行してその結果がコードとして保存され、そのコントラクを生成し、呼び出したコントラクトはstack上で新しいコントラクトのアドレスを受け取れるという点だ。
##[DeactivateとSelf-destruct]
ブロックチェーンからコードを取り除く方法は、コントラクトがそのアドレスでselfdestruct操作を実行する時。実行すると、そのアドレスに保存されている残りのEtherは指定されたアドレスに送金され、そのコントラクトのstorageとコードは状態から取り除かれる。
###注意
selfdestructのコールをコントラクトのコードが含んでいなかったら、delegatecallやcallcodeを用いて、同様の操作ができる。全ての関数を返して内部の状態を変えるdisableを代わりに用いることで、あなたのコントラクトをdeactivate(非活動状態)にすることができる。これをするとすぐetherが返され、コントラクトは使えなくなってしまう。
###警告
selfdestructでコントラクトが取り除かれても、コントラクトはブロックチェーンの履歴の一部にあり、おそらくイーサリアムノードに保持され続ける。selfdestructはハードディスクからデータを消去するのと同じではない。