# 本書について

[Ethereum入門](http://book.ethereum-jp.net)は、分散アプリケーションプラットフォーム「Ethereum（イーサリアム）」の技術入門書です。 Ethereumがどのように動作するのか、Ethereumを用いてどのように分散アプリケーションを開発していくか、について解説していきます。

Ethereumプロジェクトは最初の安定版（Homestead）リリースがされましたが、今後仕様が変更になる場合があります。仕様変更に伴い本書も逐次内容を変更していきます。

また本ドキュメントは**2018/3/10 現在、制作中です。**

本ドキュメントはオープンなプロジェクトであり、そのため協力者を広く求めています。本書のソースコードは[GitHub上](https://github.com/a-mitani/mastering-ethereum)で公開されています。

本書への追記や修正などありましたら、上記[GitHub](https://github.com/a-mitani/mastering-ethereum)にてIssueの発行、またはPull requestをお願いいたします。

本ドキュメントは [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/) のもとで公開されています。


# Ethereumとは何か？

[Ethereum](https://www.ethereum.org/)（イーサリアム）は分散アプリケーションのためのプラットフォームであり、2013年12月以降からオープンソースプロジェクトとして開発が進められているものです。2016年3月14日に最初の安定版（Homestead）リリースがされました。

インターネットの登場以来、私たちは、メール、SNS、電子決済、クラウド・ファンディングなど数えきれないほどのWebサービスを利用して日々を生活しています。これらのサービスのほぼ全てにおいて、その運営に何らかの中央管理システム（組織）の存在が必須でした。

例えばSNSでは、個人がアップロードしたデータをFacebookやTwitterといった企業が中央で一元管理することでサービスが成り立っています。またクラウド・ファインディングでは、[Kickstarter](https://www.kickstarter.com/)のような企業が、資金調達の仲立ちをし、その中で集まった資金についての管理（資金調達希望者が提示した最低金額以上の資金が集まれば資金調達希望者に渡し、そうでなければ渡さない等）を行うことで、サービスが成り立っています。 また、インターネットの基盤であるドメイン名も、[ICANN](https://www.icann.org/)を中心とした管理組織によって管理がなされています。

このような中央管理システムの存在するサービスは以下の点で欠点があります。

* 可用性： 中央管理システム（組織）が存在する以上、その中央組織が何らかの理由で潰れればサービスは存続できません。また、組織が存続している場合でも[実際にEvernoteでもあったように](https://blog.evernote.com/blog/2010/08/09/july1/)、障害によるデータ消失の危険が避けられません。
* プライバシー：例えばSNSなど、個人の生活（プライバシー）のデータを私的企業が一手に握ることは、データ漏洩の危険性、企業によるデータの不正利用の危険性を考えると好ましい物ではありません。
* 検閲：中央の組織により管理されたサービスは、そのサービス提供者による独自の検閲が少なからず入ります。検閲するかしないかは、「サービス提供者（中央管理者）」の手に握られ、たとえそれが公序良俗に「反しない」ものであっても検閲の対象になる可能性があります。

Ethereumは、「ブロックチェーン」と呼ばれる技術をベースに、なんら特別な管理者のいないP2Pシステム上で様々なサービスを実現するための基盤を提供するものです。つまり、FacebookやTwitter、KickstarterやICANNといったような、中央で管理する機関（私的企業）の存在を必要とせずに同様のサービスを実現する基盤をEthereumは提供します。

Ethereumがどのようなものかを詳しく見ていくために、まずはベースとなる「ブロックチェーン」技術の革新性について見ていきます。


# ブロックチェーン革命

## 中央機関の存在しない通貨：ビットコイン

2008年のNakamoto氏による論文[「Bitcoin: A Peer-to-Peer Electronic Cash System」](https://bitcoin.org/bitcoin.pdf)の発表と、その後の有志による[ビットコイン](https://bitcoin.org)の開発は、通貨の世界に革新を起こしました。

ビットコインを利用するためのソフトはオープンソースで提供され、PCからスマートフォンまで様々なデバイス上で動作します。ユーザーはネットワークを通じてビットコインをやり取りすることで、従来の通貨で行うほぼ全てのこと、つまり物品の売買から個人や組織への送金、そして融資も行なうことが可能です。ビットコインには国境や地域の概念がなく世界共通通貨であること、それにより海外への送金も非常に高速かつ安全で低コストに行えます。以上のような理由からビットコインは通貨の理想形と考えれられています。

このような通貨としての利便性はもちろんですが、ビットコインの最も重要な革新性は、従来の（電子マネーを含む）通貨とは異なり、通貨発行や決済にいかなる中央機関や管理者も必要としないP2Pの通貨システムであるということにあります。

冒頭に挙げたNakamoto氏の論文は、「ビザンチン将軍問題」と呼ばれる分散コンピューティングの分野での難問に初めて実用的な解を与えるものでした。そしてこの発明こそが、中央機関の必要としない通貨システムの実現の鍵となるものでした。

「ビザンチン将軍問題」とは、不特定多数のノードで構成され潜在的に悪意のあるノードも含まれるようなP2Pネットワークの中で、各ノードの情報交換によって通貨の取引情報（例えば誰から誰にいくら支払った等）にネットワーク全体で合意を形成することは可能か？可能である場合はどのように行えばよいのか？という問題です。

P2Pは不特定多数のノードがランダムに接続されたネットワークです。例えば、P2Pのネットワーク内で悪意のあるノードがAに$100を送金したという情報をそのノードに繋がっているノードの一つに送り、同時に同じ$100をBに送金したいう情報を別のノードに送信したとしたらどうなるでしょう（二重支払問題）。それぞれの情報を受け取ったノードがそれらの情報を信じて動作すると、ネットワーク内の資金の流れの情報に整合性が無くなり、たちまちこの通貨システムは破たんしてしまいます。

Nakamoto氏はブロックチェーンとプルーフ・オブ・ワークという仕組みを導入することで、P2Pのシステム上で通貨システムを実現しようとする際に生まれるこの問題を解決することに成功しました。次節以降で、ビットコインの動作の概略とともに、どのように解決したのかについて見ていきましょう。

## ビットコインでの送金の仕組み

技術的には、ビットコインの世界では、実際に何らかの電子的なコインが存在しそれをやり取りしているわけでは*ありません*。「送信者から受信者へある一定量の額面を移動させる」という取引（トランザクション）の中で各ユーザーのビットコインの保有額が暗に示されるものです。

つまり、ある時点でのあるユーザー（のアドレス）が保持するビットコインの量は、その時点より以前にそのユーザーに向けて支払われたトランザクションのうち、まだ他の誰かに支払うために使われていないトランザクション（UTXO: Unspent Transaction Output ）を寄せ集め、そのそれぞれのUTXOの額面の総和になります。

例えば、太郎がビットコインを始めようとアカウント（アドレス）を作成し、その後、友人Aから 10 BTC、友人Bから 20 BTC のビットコインを送ってもらったとします。それ以降、太郎は誰にもビットコインを支払っていないとすると、太郎は２つのUTXO を持っていることになります。そしてその総額が 30 BTCなので、太郎はビットコイン30 BTC を保有しているということになります。

さて、ここで太郎が花子に 25 BTC を送金したいとするとどうなるでしょうか？ UTXO自体はトランザクションの情報なので、その額面を分割することはできません。そのため太郎は「自分の持っている２つのUTXO （計 30 BTC）を使って、25 BTC を花子のアドレスに、5 BTC を *自分自身のアドレスに* 送金する」という新しいトランザクションを生成します。これにより花子と太郎はそれぞれ 25 BTC、5 BTC のUTXOを新たに得ることになります。これは現実世界で950円支払うのに千円札で支払い、50円のお釣りを受け取ることに似ています。

## ブロックチェーン

従来のように中央管理機関が存在している通貨システムであれば、太郎は自ら生成したトランザクションの情報をその中央機関に送信し、その機関は受信したトランザクションの情報に基づいて、自ら管理する取引台帳にその情報を更新すればよいだけです。

システムの参加者は、この信用に足る中央機関の管理する台帳が「正」であると皆で「合意」することができます。また、たとえ太郎に悪意があって、花子に 25 BTC を送った後に同じUTXOを使って 25BTC を別の人に送ろうとしても、中央機関はそのUTXOは使用済みと知っているので、「使えない」とすればよいだけです。非常にシンプルです。

一方、P2Pのネットワーク上で動作するビットコインは、代表して台帳を管理する中央機関（システム）が存在しません。そのため、各ノードが「ブロックチェーン」と呼ばれる取引台帳をネットワークへの参加者間で共有・管理し、その台帳を「正」とする合意をとります。

ビットコインのシステムでは、参加者間でビットコインの送金（＝トランザクション）が行われるとその情報がP2Pネットワーク全体に伝搬します。ネットワーク内には「採掘者」と呼ばれるノードが多数参加しており、これら採掘者は、ある時点からある時点までの間に行われたトランザクションの情報を1つの「ブロック」と呼ばれるパッケージを生成する「採掘」という作業を行います。そのブロックには、前に作成されたブロックへの参照 を含めることで、そのブロックが時系列に連なった一本のチェーン（ブロックチェーン）が連なっていきます。このブロックチェーンは、ビットコインが始まって以来の全てのトランザクション情報が含まれ、かつネットワークへの参加者全員が参照可能なものです。いわば公開取引台帳の役割を果たします。

「採掘者」はブロックを生成時、

* UTXOの所有者以外が、そのUTXOを用いて送金を行っていないか？
* 同じUTXOを複数回使用するようなトランザクションがないか？

といった、ブロックに含めるトランザクションの正当性を確認してブロック生成します。 また、その「採掘者」が生成したブロックを他のノードが受け取った際にも同様の確認をし、新しいブロックが追加されたブロックチェーンを「正」として合意するという仕組みで、取引台帳としてのブロックチェーンの正当性を合意していく仕組みをとっています。

## プルーフ・オブ・ワーク

さて、P2Pシステムの性質上、このブロックを生成する「採掘者」は特別な権限を与えられた参加者ではなく、任意の参加者が「採掘者」になることが可能です。しかし一方で、誰でも何の制限もなくブロックが生成できるとなると、皆が好き勝手にブロックチェーンを連ねていき、どのブロックチェーンが皆が合意する「正」のブロックチェーンかが分からなくなる事態になります。

そこでビットコインでは、「プルーフ・オブ・ワーク」という仕組みを導入します。これは、ブロックを採掘する際の条件に、その生成するブロックのヘッダ・データのSHA256ハッシュ値が、規定された値以下でなければならないという条件を課すものです。この制限を満たすために、採掘者はnonce（ノンス）と呼ばれる付加データをヘッダに追加することで、ハッシュ値が規定された値以下になるように調整を行います。SHA256のような暗号学的ハッシュ関数は、出力されるハッシュ値が元のデータからは予見できないように設計されている関数のために、採掘者は条件を満たすハッシュ値が出力される（＝採掘に成功する）までナンスの値を変更しながら試行錯誤を繰り返します。

多数参加している採掘者の中で最初に採掘に成功した採掘者は、その情報をビットコイン・ネットワーク内に発信します。それを受信した他の参加者は採掘されたブロックを調べ、

* 前のブロックの参照が含まれているか
* プルーフ・オブ・ワークの条件を満たしているか
* ブロックに含まれているトランザクションに不整合はないか

などを確認し、問題がないことが分かればそのブロックが「正」として合意します。

採掘に成功したノードには、インセンティブとして25 BTC の報酬が与えられます。この報酬を目当てに多数の採掘者がビットコイン・ネットワークに参加し、常に採掘競争を行っています。

プルーフオブワークの制限は、ネットワーク全体で「採掘者」達が10分に１回程度の頻度でその条件に合うハッシュ値を生成するノンスを見つけ、新しいブロックを採掘できる程度に動的に調整されます。

## ２重支払問題の解決

このブロックチェーンとプルーフオブワークの組み合わせにより、悪意のある参加者（攻撃者）が２重支払を行うことを防ぐことが可能になります。少し具体的な例として攻撃者が以下のように２重支払いを行って商品をだまし取ろうとした場合のケースを考えましょう。

1. 攻撃者が、あるEC業者から商品を購入し100BTCを送金する。
2. EC業者は100BTCが送金されたことをブロックチェーンの記録を見て確認する。送金されたことが確認できたら商品を発送する。
3. 攻撃者が商品を受け取る。
4. 攻撃者が業者に支払った100BTCをなかったことにするために、同じ100BTCを自分自身に送金したというように、ブロックチェーンを書き換える。

ステップ１の送金の事実が、ここでは仮にブロック番号2000番のブロックに記録されていたとします。ブロックが生成され、ネットワークがそれを受け入れた時点（他の採掘者がそのブロックに連なる次のブロックを採掘し始めた時点）でビットコイン・ネットワーク内で「攻撃者からEC業者への100BTCの送金した」という事実が存在するという合意が得られたことになります。攻撃者が送金の事実を消そうとした場合、このブロック番号2000番のブロックに含まれるトランザクション情報を書き換える必要があります。トランザクションの中身が変わっているために既に存在するブロック番号2000のハッシュ値も変わるため、攻撃者はこの書き換えたトランザクションの内容で番号2000のブロックを再び採掘する必要があります。また、採掘しなおしたブロックはオリジナルのブロックとは異なるハッシュ値を持っているため、他の採掘者が採掘した2001番以降のブロックはもはや攻撃者が書き換えたブロックの方を参照しません。

ビットコインのブロックチェーンのルールとして、Forkができた場合は、最も長いForkを正とするというルールがあるため、攻撃者が2,000番のブロックを採掘したとしても他の採掘者はそれに連なるブロックを採掘しようとはせず、正当な方の分岐の採掘を行おうとします。一方で攻撃者は、自分のみで2,000番のブロックに続くブロックを採掘していこうとするのですが、攻撃者が自分のブロックチェインが正統なほうのチェーンより長く連ねるには、正当な方のチェーンを採掘し続けている残りのネットワーク全部の計算パワーを上回る必要があります。ビットコイン・ネットワークに十分な採掘者が参加していれば、攻撃者単独で残りの採掘者達の計算パワーには勝つことは容易ではありません。（攻撃者が単独で全採掘者の計算パワーの51%を占める必要があります。）そのため、２重支払が出来ない仕組みとなっているのです。

## ブロックチェーンの応用

Nakamoto氏の発明の本質は、いかなる中央機関も存在しないP2Pネットワーク上で、「合意」の形成を行うことを可能にしたことにあります。送金の事実についての合意形成を実現することで、P2Pネットワーク上に「通貨」を実現したビットコインは、このブロックチェーンによる革新の一つの応用に過ぎません。事実2009年以降、ブロックチェーンによる合意形成を応用した様々なサービスが生み出されています。

一つの例が[Namecoin](https://namecoin.info/)です。Namecoinは名前登録を分散システム上で行うものです。例えば、Webサイトなどに用いられるドメイン名は現在ICANNという組織を中心に管理されているものです。このようなドメイン名の管理をブロックチェーンを利用してP2Pシステム上で実現しようとするのがNamecoinです。「いつ誰がどのドメイン名を登録した」という事実をブロックチェーンに登録し、それをネットワーク参加者の誰もが参照可能な公開ドメイン登録台帳として管理していきます。Namecoinは、ブロックチェーンの応用の中でも最も古く成功した例として知られています。

この他にも、[Storj](http://storj.io/)（分散ストレージ）、[Proof of Existence](http://www.proofofexistence.com/)（ドキュメント存在証明）などの様々な応用サービスがローンチされてきています。ブロックチェーンを用いたP2Pの分散型のサービスは現在の時点では思いつかないアイデアのサービスに広がっていくかもしれません。

## 脚注

[This work](http://book.ethereum-jp.net/) is licenced under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).


# Ethereumとは

## 分散アプリケーション開発の障壁

前節で、ブロックチェーン技術の革新性と、通貨（ビットコイン）だけに収まらない応用の可能性について述べてきました。

ブロックチェーン技術を用いた新たな応用サービスをローンチするためには、２つの選択肢があります。１つは新たなサービスのために新しいブロックチェーンを構築しそれを使ってサービスを行うこと。２つめは、ビットコインのような既存のブロックチェーンを利用しその上にサービスを構築するというものです。前節に挙げた応用例では、[Storj](http://storj.io/) や [Namecoin](https://namecoin.info/) は前者のタイプであり、[Proof of Existence](http://www.proofofexistence.com/) は後者のタイプになります。

新しいブロックチェーンを構築することは、非常に敷居の高い方法です。実装とテストに相当の工数がかかります。さらに重要なのは、ブロックチェーンを用いた合意形成がサービスのローンチ当初から安定して動作するためには、事前に相当数の参加者が集まっている必要があることです。これは需要の少ないニッチなサービスを展開する際には、非常に致命的な問題になります。

一方で、既存のビットコインのブロックチェーンを利用したサービス提供する場合は、あくまでビットコイン自体の設計上の制限に従う必要があり、非常に不自由なものとなってしまします。

## Ethereumとは

[Ethereum](https://www.ethereum.org/)（イーサリアム）は、上述のようなブロックチェーンを利用した分散アプリケーションを開発しサービス提供を行う際の障壁を取り除くことを目的とした「分散アプリケーションプラットフォーム」です。そのプラットフォームを形作るためのプロトコル定義や実装が[オープンソース・プロジェクト](https://github.com/ethereum)としてグローバルな有志により行われています。

Ethereumは独自のP2Pのブロックチェーンネットワーク（Ethereumネットワーク）を構築し、分散アプリケーションが動作する実行環境の役割を果たします。様々な分散アプリケーションがEthreumのブロックチェーンを共有して利用することで利用者が少ないニッチな分散アプリケーションでも、ブロックチェーンを利用した「合意形成」が安定して動作する環境を提供します。

また、分散アプリケーションのコードは、ブロックチェーンに組み込まれプルーフ・オブ・ワークの仕組みにより、改ざん不可能になります。このコードはEthereumネットワークに参加する各（採掘者の）ノード上で実行され、その結果の状態もブロックチェーンに組み込まれ、やはり改ざんが不可能になります。

ビットコインはブロックチェーンの技術を用いて悪意のある参加者が参加する可能性のあるP2Pネットワーク上で「取引」を正しく動作させる環境でした。一方でEthreumは、取引だけでなく任意のアプリケーション（処理）をこのようなP2Pのネットワーク上で正しくに動作させることを可能にする環境を提供するのです。

ここで、もう少し詳しくEthereumの仕組みを見ていきましょう。（詳細は「Ethereumの内部」の章で解説します。）

## Ethereumの仕組み

### 内部通貨：ether

Ethereumでは、「ether」という独自の内部通貨が規定されています。ビットコインと同様、それ自体が価値を持つ通貨としての利用も可能ですが、より重要な事はetherがEthereum内で分散アプリケーションやスマート・コントラクトを実行するための「燃料」の役割を果たすという事です。Ethereumは上述のように、このプラットフォーム上で動作する分散アプリケーションに対して任意の処理を可能にしており、それぞれの分散アプリケーション間でその動作に必要な計算資源の量は異なってきます。そこで、Ethereumでは、分散アプリケーションを実行するためには、その処理の重さに応じた燃料が必要」とすることによって、Ethereum上で動作する分散アプリケーション間での計算資源の割り当ての平等性を確保しています。

内部通貨etherの単位は通貨名と同じでether（またはETH）ですが、米国の通貨で 1 dollar = 100 cent と規定されているように、etherも利便性のために、より少額のetherに対して下記のように単位名が決められています。

* 1 ether = 1,000 finney
* 1 ether = 1,000,000 szabo
* 1 ether = 1,000,000,000,000,000,000 wei

### アカウント

Ethereumには、「アカウント」と呼ばれるオブジェクトが既定されています。アカウントは 20 Byte のアドレス（例：0x4c84913cc41f2aad9c24d82bfde598c91cdd33d3） により参照されます。アカウントは主に次の４つのフィールドを持ちます。

* nonce：そのアカウントが送信した累積トランザクション数
* ether balance：そのアカウントが所有するether量
* contract code：コントラクト・コード（EOAの場合は空）
* storage：そのアカウントが保持する任意のデータ

この各フィールドのデータ（詳細は「Ethereumの内部」章で解説します）は、アカウント間でトランザクションが発生することにより変化します。つまり、アカウントの「状態」がトランザクションによって変化していきます。

「アカウント」には２つのタイプが存在します。一つは「Externally Owned Account（EOA）」、もう一つは「Contract」です。EOAは、我々ユーザーにより生成されコントロールされるアカウントです。ユーザーの任意のタイミングでトランザクションを生成し、他EOAへのetherの送金、新しい Contract の生成やコントラクト・コードの実行を行います。

一方でContract は、EOAからトランザクションを介して生成されます。Contractは一種の自動エージェントであり、EOAが発信するトランザクションをトリガに、コントラクト・コードを実行します。

### トランザクション

EthereumではEOAから任意のタイミングでトランザクションを送信することで、各アカウントの状態が変化します 。EOAがトランザクションを生成しそれをEthereumネットワーク上に送信します。採掘者は受信したトランザクションの正当性をチェックし問題なければ、そのトランザクションの情報とトランザクションの内容に基づいて変化した最新のアカウントの状態をブロックチェーンに埋め込みます。

トランザクションには主に以下の情報が含まれます。

* ether送金額
* 相手先アドレス
* 送信アカウント署名
* 任意データ
* STARTGAS値
* GASPRICE値

最初の３つはビットコインのような暗号通貨のトランザクションと同じで、それぞれ、Ethereumの内部通貨であるetherの送金額と相手のアドレス、そしてトランザクションの送信者がether送金元アドレスの所有者であることを証明するデジタル署名です。

「任意データ」はトランザクションの相手先が Contract である場合に、そのコントラクト・コードに引き渡すデータ格納します。

例えばIPアドレスとドメイン名の紐づけを管理するドメイン管理の分散アプリケーションを考えてみましょう。その場合にユーザーは、自分が登録したいIPアドレスとドメイン名の情報を分散アプリに対して引き渡し、分散アプリ側でその登録情報を管理することになります。このようなことを実現するために、ユーザーは分散アプリの処理（ここではドメインの登録情報の管理）を担う Contract のアドレスを「相手先アドレス」に、かつ、自分の登録したい情報（ここではIPアドレスとドメイン名）を「任意データ」に格納したトランザクションを発生させます。一方そのトランザクションにより「任意データ」に格納されたデータを入力値としてコントラクト・コードが実行され、今回引き渡されたデータがすでに登録済みのものではない場合、Contract の`storage`フィールドに格納された登録済みドメインリストに今回の登録情報が追加されることになります。

STARTGAS値と、GASPRICE値は、トランザクション手数料として支払うetherの量を規定する情報です。トランザクションに必要な手数料は、トランザクションが実行するコードの処理の数や、トランザクションのデータの大きさに応じて「gas」という単位で計算されます。トランザクションで支払う最大のgas量がSTARTGAS値であり、そしてその「gas」と内部通貨etherとの交換レートがGASPRICE値になります。

#### トランザクションの処理の流れ

ここでトランザクションによりどのようにアカウントの状態が変更されていくのかの処理の流れを見ていきます。大まかに以下のようになります。

1. EOAがトランザクションを生成し、Ethereumネットワーク上に送信する。
2. ネットワーク内の採掘者がトランザクションを受信する。
3. 採掘者は、署名の正当性など、受信したトランザクションのデータに問題がないかをチェック。問題がある場合はエラーとして以降の処理を行わない。
4. 採掘者はトランザクション内のSTARTGAS値とGASPRICE値を参照。「STARTGAS値 × GASPRICE値」の量のetherを、前払い手数料として、トランザクションを送信したアカウントの保有するetherから引く。もしetherの保有量が「STARTGAS値 × GASPRICE値」よりも少なければエラーとして以降の処理を行わない。
5. 残りGAS ＝ STARTGAS値 とする。
6. トランザクション・データの大きさ1バイト当たり5 gasを残りGASから引く。
7. トランザクション内で指定された相手に対して、指定された額のetherを送金。また「トランザクションの相手」が Contract の場合は、Contract の持つコードを実行。
8. 送金額のetherを送金者が保有していない、または、コードを実行中に残りGASがゼロになった場合には、手数料の支払情報のみを残し、元の状態にロールバックさせる。トランザクション実行前の状態から、トランザクション実行のための手数料分だけトランザクションの送信者の保有etherから引き、採掘者の保有額にそれを足した状態を終状態とする。
9. 送金、またはコードの実行が正常に終了し、GASが余っている場合は、その余ったGASをトランザクションの送信者に対して戻す。

### ブロックチェーンと採掘

ビットコインのシステムで、ブロックチェーンはビットコイン・ネットワーク上で発生したすべてのトランザクションを記録した、誰でも参照可能な公開取引元帳の役割を果たしていました。

Ethereumのブロックチェーンも同様に公開元帳の役割を果たします。ただビットコインの場合とは異なり、Ethereumのアカウントのブロックチェーンには、トランザクションだけでなくEthereumネットワークの全アカウントの最新の状態に関する情報も記録されます。

つまり、ブロックチェーンにはトランザクションとアカウントの状態が記録されていき、そのブロックチェーンに書き込まれた状態を「正」とするEtherumネットワーク内の合意が形成されていきます。

Ethereumネットワーク内の採掘者は、etherの報酬を目当てに、ブロックの採掘競争を続けます。Ethereumでは、新しいブロックが平均して12秒に1回採掘されるように動的にプルーフ・オブ・ワークの難易度を調整されるように設計されています。

Ethereum では、採掘が成功すると、

* 1採掘当たり固定で2 ether
* ブロックに含まれる全てのcontractのコードを実行した際に消費したgasに相当するether
* ブロックに含んだ1つのUncleブロック当たり1/32 ether

の報酬が採掘者に与えられます。

## Ethereumを支えるエコシステム

Ethereumはオープンソース・プロジェクトとしてETHDEVチームとグローバルな有志により様々な開発が進められていることは既に述べました。今後Etherumを使って分散アプリケーションを開発していく上で有用なものを中心にいくつか紹介します。

* [**Ethreum White Paper**](https://github.com/ethereum/wiki/wiki/White-Paper)： Ethreumのコアの仕組みについて比較的平易に説明された論文です。本書もかなりの部分でこのホワイトペーパーを参考にしています。
* [**Ethereum Yellow Paper**](http://gavwood.com/paper.pdf)： Gav Woodにより著されたEthreumの公式プロトコル仕様書。現在までに様々な言語でEthereumのノードが開発されていますが、それらはこのYellow paperに従い実装されています。現在も[Github上でメンテナンス](https://github.com/ethereum/yellowpaper)されています。
* [**ethstats**](https://ethstats.net/)：Ethreumネットワークの状況をモニタするダッシュボードが提供されています。ブロックの採掘状況やその難易度等が確認できます。

## 脚注

[This work](http://book.ethereum-jp.net/) is licenced under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).


# まずは Ethereum に触れてみる

前の章では、ブロックチェーン技術の革新性と、Ethereumがブロックチェーン技術を用いた分散アプリケーションやスマート・コントラクトの開発を容易にするプラットフォームであることを説明してきました。

では実際にEthereum上で分散アプリケーションやスマート・コントラクトを開発していく流れを見ていきましょう。

この章では最初にEthereumのフル・クライアントであるgethのインストールの方法を解説します。そしてgethを使ってetherの採掘と送金を行う方法を解説します。最後に、最も単純なContractを作成し、実際に動作させるところまでを解説していきます。

※ ここでは分散アプリケーションやスマート・コントラクトを開発していく目的で、フルノードである「geth」を利用する方法を記載していきます。一方で、Ethereumを仮想通貨としてのみ利用し採掘（マイニング）も行なわない場合には、各種ウォレットを利用する方が簡易です。ウォレットについての詳細は[Appendix](/appendix/using_metamask)に記載していますので参照ください。


# Gethをインストールする

Ethereumを利用する場合、まずはEthereumのP2Pネットワークに参加する必要があります。ネットワークへの参加はEthereumクライアントをインストールし起動することで参加が可能になります。

Ethereumでは、Ethereumの仕様を実装した幾つかのEthereumクライアントが存在しますが、現在のところ推奨されているクライアントは「Geth」です。Gethはプログラミング言語[Go](http://golang.org/)により実装されたCUIクライアントであり、GethをインストールすることでEthereumネットワークにフル・ノードとして参加し、

* etherの採掘
* etherの送金
* スマート・コントラクトの生成
* トランザクションの生成
* ブロックチェーンの確認

といった動作が可能になります。

本節では、Gethのインストール手順を解説します。

## UbuntuへのGethのインストール

Ubuntu OSを使用している場合、下記の一連のコマンドを実行するとでGethがインストールされます  。

```
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum
```

また、sudoコマンドの実行のためにパスワードが求められる場合があるので、その場合は適宜パスワードを入力します。

コマンド実行が完了した後、実際にgethがインストールされたかを確認するために、

```
$ geth --help
```

のコマンドを実行してみましょう。gethコマンドのオプション情報が表示されれば、正しくインストールされています。

### Gethのアップデート

Ethereumの開発は現在Proof of Concept の第9フェーズであり、正式リリースではありません。そのため、クライアント・ソフトにおいても頻繁にアップデートが行われております。\
Gethをアップデートする際には`apt-get`コマンドにより、以下の手順で行います。

```
$ sudo apt-get update
$ sudo apt-get upgrade
```

## Mac OS へのGethのインストール

Homebrewを用いたインストールとソースからインストールする方法があります。

### Homebrew を用いたGethのインストール

Homebrewをインストールがされてあれば、次のコマンドだけでインストールできます。

```
$ brew tap ethereum/ethereum
$ brew install ethereum
```

### ソースからGethをビルドする

go-ethereumのレポジトリをクローン

```
$ git clone https://github.com/ethereum/go-ethereum
```

そして、次のコマンドを実行することでGethをビルドできます。(ビルドにはGoが必要になります)

```
$ cd go-ethereum
$ make geth
```

## Windows へのGethのインストール

Windows環境へのインストールはUnix系統のOSへのインストールと異なり、若干手順が煩雑です。Windows環境へのインストールは[こちら](https://github.com/ethereum/go-ethereum/wiki/Installation-instructions-for-Windows)に詳しく記載されているので、参考ください。

## 脚注


# プライベート・ネットに接続する

Gethのインストールが完了したら早速Gethを起動します。

Ethereumでは以下の３つの形態のP2Pネットワークを構築しブロックチェーンを運用していくことが可能です。

* **パブリック・ネットワーク**：不特定多数のノードのノードが参加し、かつその参加に制限が全くないネットワークです。参加ノードはそのネットワーク上で共有管理されたブロックチェーンに対して自由に、読み取り、トランザクションの発行、マイニングが可能です。仮想通貨としてのEthereumや、多くのパブリックなdAppはこのパブリックネットワーク上で運用されています。
* **コンソーシアム・ネットワーク**：あらかじめ参加を許されたノードのみが参加することが可能なネットワークです。参加を許されるノードは一つの組織のみに管理されたものとは限らず、複数の利害関係が一致しない組織がそれぞれのノードを管理することが通常です。例えば国際送金の管理を行うブロックチェーンを構築したい場合、予め参加を許された複数の金融企業がそれぞれ管理するノードをこのP2Pのネットワークに参加することで、一つの企業にのみ管理されたシステムではない半非中央集権なシステムが構築可能になります。
* **プライベート・ネットワーク**：一つの組織のみに管理されたノードのみが参加することが可能なネットワークです。ネットワークは自身の管理下に置くことが可能になり、中央集権的なP2Pシステムが可能になります。

ここでプライベート・ネットワークは、自分自身のみのネットワークなので容易にEtherの採掘が可能ですし、安全性も高いネットワークです。そのため、Ethereumの動作を調べたり、分散型アプリケーション（Dapp）の開発作業など個人的な作業を行うには、プライベート・ネットワークを立ち上げてそこでいろいろ弄ってみると便利です。

そこで本節では、インストールしたGethを起動し、プライベート・ネットに接続するところまでを解説していきます。

## Genesisファイルを作成する

Genesisファイルとは、ネットワークでやり取りされるブロックチェーンの最初（Block番号 "0"）のブロックであるGenesisブロックの情報を記述したファイルです。プライベート・ネットでは独自のブロックチェーンをやり取りしていくため、独自のGenesisブロックを定義したGenesisファイルを用意して利用します。

まず任意の場所にプライベート・ネットのブロック情報やノード情報など各種データを格納するディレクトリ（データ・ディレクトリ）を作成します。ここでは、ログイン・ユーザー（今回の例ではubuntu）のhomeディレクトリ直下に作成します。

```
$ mkdir /home/ubuntu/eth_private_net
```

次に上記ディレクトリ内にjson形式の下記の内容 を記述した`myGenesis.json`ファイルを配置します。

```javascript
{
  "config": {
    "chainId": 15,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0
  },
  "nonce": "0x0000000000000042",
  "timestamp": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "",
  "gasLimit": "0x8000000",
  "difficulty": "0x4000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x3333333333333333333333333333333333333333",
  "alloc": {}
}
```

## Gethをプライベート・ネットで起動する

### genesisブロックの初期化

データ・ディレクトリとgenesisファイルを作成したら、以下のコマンドを実行しブロックチェーン情報をgenesisファイルの内容で初期化します。

```
$ geth --datadir /home/ubuntu/eth_private_net init /home/ubuntu/eth_private_net/myGenesis.json
```

本コマンドを実行すると、`--datadir`で指定したディレクトリ以下にディレクトリが新しく作成されて、その中にgenesisブロックのブロックチェーン情報が保存されます。ここで実行時に

```
WARN [02-04|09:03:55] No etherbase set and no accounts found as default
```

という警告が表示されますがこのノード（geth）でのデフォルトのウォレットのアドレスを作成していないために表示されるものです。これは次節で作成していくので、現時点では無視して構いません。

### gethの起動

次に以下のコマンドを実行することでGethを起動します。

```
$ geth --networkid "15" --nodiscover --datadir "/home/ubuntu/eth_private_net" console 2>> /home/ubuntu/eth_private_net/geth_err.log
```

ここで各オプションの意味は以下の通りです。

* `--datadir` :本オプションはgethの動作時のブロックチェーンデータや各種ログの出力先を指定します。genesisブロックの初期化で指定したディレクトリと同一のものを指定してください。
* `--networkid "15"` ：本オプションで任意の正の整数のIDを指定することで、ライブ・ネットとは異なるネットワークを立ち上げることが可能です（ここでは15を指定）。genesisブロックの初期化で指定した`chainid`と同一の値を指定する必要があります。
* `--nodiscover` ：Gethはデフォルトで自動的に（同じネットワークID）のEthereumネットワークのノード（Peer）を探し接続を試みます。プライベート・ネットでは未知のノードとの接続を避けるため、このオプションで自動Peer探索機能を無効にします。
* `console`：Gethには採掘やトランザクションの生成などを対話的に進めることができるコンソールが用意されています。`console`サブ・コマンドを指定することで、Gethの起動時に同時にコンソール立ち上げることが可能です。なお、`console`サブ・コマンドを付加せずに、Gethのプロセスをバックグラウンドで起動させておき、後からそのプロセスのコンソールを起動する事も可能です（下記TIP参照）。

上記コマンドを実行すると、下記の実行結果のように、幾つかの情報の表示の後に「>」のプロンプトが表示され、コンソールが起動されます。今後、特にことわりのない限りこのコマンドで起動したGethプロンプト上で作業していく前提で進めていきます。

```
Welcome to the Geth JavaScript console!

instance: Geth/v1.7.3-stable-4bb3c89d/linux-amd64/go1.9
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
```

実際に今回立ち上げたプライベート・ネットのGenesisブロックが`myGenesis.json`に記載されたものになっているのかを確認してみます。Gethプロンプト上で

```
> eth.getBlock(0)
```

のコマンドを実行してみます。このコマンドは指定したブロック番号のブロック情報を表示するもので、今回はブロック番号"0"を指定してGenesisブロックの情報を表示します。下の結果のように例えば`difficulty`が`myGenesis.json`に指定したものになっているはずです。（ただし16進表記から10進表記に変換されています。）

```
> eth.getBlock(0)
{
  difficulty: 16384,
  extraData: "0x00",
  gasLimit: 134217728,
（中略）
  miner: "0x3333333333333333333333333333333333333333",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
（後略）
}
```

#### ■■ TIP ■■

今後Gethを使用していくなかで、採掘等のためにGethをバックグラウンドで常時起動しておき、必要に応じてそのGethプロセスに対してコンソールを用いて対話的に操作をしたいといった場合が発生します。その際は、下記のように`attach`サブ・コマンドを利用することで、既に起動されたGethプロセスのコンソールを起動することが可能です。

```
$ # gethプロセスをconsoleサブ・コマンドを付加せず、かつ最後に"&"を付加することで、バックグラウンドで起動します。
$ # この場合、起動時にはコンソールは立ち上がりません。
$ geth --networkid "15" --nodiscover --datadir "/home/ubuntu/eth_private_net" 2>> /home/ubuntu/eth_private_net/geth_err.log &
$
$ # attachサブ・コマンドを用いて先に立ち上げたプロセスのコンソールを立ち上げます。
$ # ここで、ipc:以降に先に立ち上げたgethプロセスのデータ用ディレクトリ以下のgeth.ipcファイル（実際はソケット）のパスを指定します。
$ geth --datadir "/home/ubuntu/eth_private_net" attach ipc:/home/ubuntu/eth_data/geth.ipc

instance: Geth/v1.3.5/linux/go1.5.1
（実行結果 中略）
modules: admin:1.0 db:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 shh:1.0 txpool:1.0 web3:1.0
>
```

#### ■■ TIP ■■

以降の説では`geth`の様々な内部コマンドを利用してEthereumの動作を見ていきますが、内部コマンドの一覧と用途についてはEthreumのJavascript APIであるweb3APIである[web3.jsのリファレンスサイト](http://web3js.readthedocs.io/en/1.0/)が参考になります。

## 脚注


# etherを採掘する

前節までで、Ethereumの代表的なクライアントであるGethをインストールし、テストネットへの接続、対話型のコンソールの立ち上げ方法を解説しました。Ethereumは内部通貨etherが規定されており、Ethereumでトランザクションを発生させるためにはetherの手数料が必要になります。この節ではetherを採掘する手順を見ていきます。

## アカウントの作成

Gethのコンソール上で新規のアカウントを作成します。Ethereumには２種類のアカウントが存在します。一つはEOA（Externally Owned Account)、もう一つはContractです。

EOAは私たちユーザーによりコントロールされるアカウントであり、我々ユーザーによる任意のタイミングで、EOAがトランザクションを発生させ、他のアカウントへのetherの送金、コントラクト・コードの実行などを行います。また、etherの採掘もこのEOAアカウントにより行われます。

一方Contractは一種の自動エージェントであり、EOAにより発生したトランザクションをトリガにContractアカウントが内部に持つコントラクト・コードが実行されます。それによりContractのフィールドのデータも更新されます。オブジェクト指向言語に馴染みのある人には、「Contractは一種のクラスのようなもので、EOAによりContractのメソッドが呼ばれ、そのメソッドが実行されるとContractの持つクラス変数が書き換えられる」というアナロジーでの説明が分かりやすいかもしれません。

ここでは、EOAを新規に作成していきます。 前節の手順に従い、Gethが起動されコンソールが表示された状態を前提とします。

まず、このノードに登録されたアカウント（EOA）を表示させてみましょう。`eth.accounts`コマンドはこのノード内で作成されたEOAのリストを表示するものです。現時点ではアカウントを作成していないため、下記のように実行しても空のリストが表示されるのみです。

```
> eth.accounts
[ ]
```

EOAの作成は`personal.newAccount("passwd")`コマンドで行います。ここでpasswdの部分は作成するEOAのパスワードです。実行時には適宜書き換えて実行してください。実行すると、作成されたEOAの20バイトのアドレスが表示されます。また、`personal.listAccounts`コマンドの実行結果にも作成したアカウントのアドレスが表示されるようになります。

```
> personal.newAccount("hogehoge01")
'0x24afe6c0c64821349bc1bfa73110512b33fa18e1'

>eth.accounts
['0x24afe6c0c64821349bc1bfa73110512b33fa18e1']
```

ここで、もう一つアカウントを作成しましょう（後で使用します）。

```
> personal.newAccount("hogehoge02")
'0x59c444d6c4f4187d1dd1875ad74a558a2a3e20b6'

> eth.accounts
['0x24afe6c0c64821349bc1bfa73110512b33fa18e1', '0x59c444d6c4f4187d1dd1875ad74a558a2a3e20b6' ]
```

【注意】パスワードを忘れると復元する手段は**ありません**。絶対にパスワードは忘れないようにしてください。また、上記の例では簡易なパスワードを用いましたが、実際には、セキュリティの観点から半角英数記号を含む長い複雑なパスワードを設定するようにしてください。

#### etherbase

ここで、`eth.coinbase`コマンドを実行してみます。すると下記のとおり実行結果には先ほど作成した2つのEOAのうちの一つが表示されます。このコマンドはetherbase（coinbaseとも呼ばれます）を表示するコマンドで、etherbaseとは、各ノードで採掘を行う際にその報酬を紐づけるEOAのアドレスを示します。

```
> eth.coinbase
'0x24afe6c0c64821349bc1bfa73110512b33fa18e1'
```

etherbaseはデフォルトではプライマリーのアカウント（`eth.accounts[0]`コマンドを実行して表示されるアドレスのEOA）が設定されますが、下記のように`miner.setEtherbase(new_adress)`コマンドで変更することも可能です。

```
> miner.setEtherbase(eth.accounts[1])
> eth.coinbase
'0x59c444d6c4f4187d1dd1875ad74a558a2a3e20b6'
```

## etherの採掘

作成したEOAのアドレスがetherbaseとしてセットされていれば、etherの採掘が可能です。 etherの採掘は`miner.start(thread_num)`コマンドで開始します。ここでthread\_num は採掘を何本のスレッドで同時実行するかを指定するパラメータです。指定しない場合は動作環境でのCPUコア数に設定されます。ここではthread\_numは指定せず、以下のコマンドで採掘を開始します。

```
> miner.start()
null
```

また、採掘を停止したい場合は `miner.stop()`コマンドを実行すれば停止できます。

```
> miner.stop()
true
```

### 採掘状況の確認

採掘を開始するとブロックが次々と生み出されていきます。ブロックチェーンに何番目のブロックまで連なっているのか（＝ブロック高）を確認するには、`eth.blockNumber`コマンドを用います。 採掘開始後しばらく すると、

```
> eth.blockNumber
145
```

といったように、ブロックが採掘されていることが確認できます。今回の結果の場合、145個のブロックが採掘されています。（今は自分だけが参加しているテストネットで採掘を行っているので、この145個のブロックは全て自分が採掘したことになります。）

**■TIP■**

なかなか採掘に成功しない場合、実際にGethで採掘処理が行われているのか不安になることが多くあります。処理が行われているかを確認する方法として`eth.mining`コマンドで採掘中か否かを表示する方法があります。採掘中であればコマンドの実行結果として`true`が返り、そうでなければ`false`が返却されます。もう一つの方法は、`eth.hashrate`コマンドで、現在の採掘処理のハッシュ・レートを確認することです。ハッシュ・レートがゼロよりも大きければ、採掘処理が行われていると考えてよいでしょう。

```
> miner.start()
null
> eth.mining
true
> eth.hashrate  //採掘処理実行時
445445
> miner.stop()
true
> eth.mining
false
> eth.hashrate  //採掘処理が行われていない場合、ハッシュ・レートは0となる。
0
```

### 採掘したブロックの内容を調べる

`eth.getBlock(number)`コマンドは、numberに任意のブロック高を指定すると、そのブロック高のブロック情報を表示することができます。 以下に、ブロック高が100と101のブロックの情報を表示してみます。

```
> eth.getBlock(100)
{
  difficulty: '137447',
  extraData: '0x476574682f76312e302e312f6c696e75782f676f312e342e32',
  gasLimit: 3141592,
  gasUsed: 0,
  hash: '0x4d3063b91cbaa12bf2de81014c1319febc9f197c93f81b0746afaffaa9496620',
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  miner: '0x24afe6c0c64821349bc1bfa73110512b33fa18e1',
  nonce: '0x28fda83cb19ed497',
  number: 100,
  parentHash: '0x5885cdec1d1410580eaaf1fb7ef9db245a735822d48e816c73d926b7c9872f15',
  sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
  size: 536,
  stateRoot: '0xacf2c3dfc512373ae6d9693207b3ac43fd4811791fec994c2eecd8fdd3333699',
  timestamp: 1439451765,
  totalDifficulty: '13551548',
  transactions: [ ],
  transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
  uncles: [ ]
}
> eth.getBlock(101)
{
  difficulty: '137514',
  extraData: '0x476574682f76312e302e312f6c696e75782f676f312e342e32',
  gasLimit: 3141592,
  gasUsed: 0,
  hash: '0xca9b241dabe753ed83d6242f226c0ad6b559c722edf5d24baff126670f70a30c',
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  miner: '0x24afe6c0c64821349bc1bfa73110512b33fa18e1',
  nonce: '0x06024dfb81cc05ef',
  number: 101,
  parentHash: '0x4d3063b91cbaa12bf2de81014c1319febc9f197c93f81b0746afaffaa9496620',
  sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
  size: 536,
  stateRoot: '0xbd43f9a44f2064c564060e585a23f7183036d83b411e14ad6b346de9d8dead02',
  timestamp: 1439451766,
  totalDifficulty: '13689062',
  transactions: [ ],
  transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
  uncles: [ ]
}
```

各項目については、「Ethereumの内部」章で詳しく説明しますが、ここでは、`miner`、`number`、`hash`、`parentHash`、`transactions`の項目に着目します。

`miner`の項目はそのブロックを採掘したEOAのアドレスを示しています。今回は採掘者は自分一人の環境のテスト・ネットなので、採掘者は自分のEOAのアドレス（eth.coinbaseで得られるアドレス）が採掘者として記録されているはずです。

`number`はそのブロックのブロック高を示しています。（今回はブロック高を指定して情報を表示しているので、指定したブロック高と同一の値が表示されているはずです。

`hash`はそのブロックのブロック・ヘッダ・ハッシュを表示しています。ブロック・ヘッダ情報をSHA-3アルゴリズム適用して得られた32-byteのハッシュ値です。この`hash`はブロックを指し示すユニークなIDとして利用されます。ここで、`hash`は、当該ブロックのデータ構造の中に含まれないことに注意してください。`hash`を知る必要がある場合には各自がブロック・ヘッダのデータを元に計算することになります。

`parentHash`は、親ブロックのブロック・ヘッダ・ハッシュを示しています。parentHashはブロック・ヘッダのデータ構造の中に含まれており、つまりは、子ブロックから親ブロックを参照していることになります。このような参照の連鎖が連なることでブロックのチェーン「ブロックチェーン」が形成されていることになります（下図参照）。

![](/files/-M41_IfUhL_Kpdt2ZV37)

### 報酬の確認

採掘者が、自身の持つ計算資源を費やして採掘を行うインセンティブは、Ethereumの内部通貨であるetherを報酬として得られることにあります。実際に採掘をしたことによりetherが得られているかを確認してみましょう。

各アカウントのetherの持ち高を参照するには`eth.getBalance(address)`コマンドを用います。持ち高を確認したいアカウントのアドレスをaddressパラメータに引き渡すことで確認が可能です。先の手順で、２つのアカウントを作成していました。それぞれのetherの持ち高を確認してみましょう。

```
> eth.accounts //作成したアカウントのアドレスを再確認
['0x24afe6c0c64821349bc1bfa73110512b33fa18e1', '0x59c444d6c4f4187d1dd1875ad74a558a2a3e20b6' ]
> 
> eth.coinbase == eth.accounts[0] //etherbaseは0番目のアカウントに紐づいている。
true
> eth.getBalance(eth.accounts[0])
'51500000000000000000'
> eth.getBalance(eth.accounts[1])
'0'
```

先に解説したとおり、coinbaseに紐づいたアカウントに採掘の報酬が与えられているのがわかります。`eth.getBalance(address)`は「wei」の単位 で持ち高が表示されます。以下の変換用のコマンドを使うことでetherの単位で表示することも可能です。

```
> web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
'515'
```

## 脚注


# etherを送金する

先の節で、採掘の報酬としてEthereumの内部通貨であるetherを取得することができました 。この節では、採掘で得たetherを他のEOAへ送金する方法と、その際に発生するトランザクションとその手数料について見ていきます。

## etherの送金

まず最初にもう一度、今回作成したアカウントのetherの持ち高を確認しておきましょう。

```
> eth.accounts // 登録されている２つのアカウントを表示。
['0x24afe6c0c64821349bc1bfa73110512b33fa18e1', '0x59c444d6c4f4187d1dd1875ad74a558a2a3e20b6' ]
> eth.getBalance(eth.accounts[0]) // etherbaseである1番目のアカウントにetherの持ち高がある（採掘の報酬）。
'72500000000000000000'
> eth.getBalance(eth.accounts[1]) // 2番目のアカウントにはetherの持ち高はない。
'0'
```

`accounts[0]`のEOAは、725 ether を保有している一方で、もう一方の`accounts[1]`のEOAはetherを保有していないのがわかります。

この状態で`accounts[0]`から、`accounts[1]`へ、5 ether を送金します。送金は`eth.sendTransaction`コマンドを用います。ここで`from`に送金元アドレス、`to`に宛先アドレス、`value`に送金額を指定します。なお、実際には送金時に送金元のアカウントのロックの解除が事前に必要なので解除を行った後に送金を行います。

```
> personal.unlockAccount(eth.accounts[0]) //アカウントのロック解除。パスワードを求められるので、適宜パスワードを入力する。
Unlock account 24afe6c0c64821349bc1bfa73110512b33fa18e1
Passphrase:
true

> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(5, "ether")}) //送金の実行。実行結果としてトランザクションIDが返される。
'0xc86c2a5bdf651f54095eca87e487d4f68f12030dd559f0377e9e7bf1566b9b28'
```

送金額はweiの単位での指定のため、単位変換関数であるweb.toWeiを用いています。このコマンドを実行すると、実行結果としてトランザクションIDが返されます。コマンド実行後、しばらくして送金先のether保有額を確認すると、下記のように、問題なく5 ether (= 5 × 10^18 wei） が送金されていることが分かります。

```
> eth.getBalance(eth.accounts[1])
'5000000000000000000'
```

【注意】送金の際は、採掘処理をバックグラウンドで実行しておく必要があります。今回の例ではテスト・ネットでの送金であり、採掘者は自分自身しかいないため、自身が採掘を実行中でないとトランザクションが処理されません。

## トランザクション手数料

同じように今度は逆に、'0x59c44...'のアカウントから、'0x24afe...'に 3 ether 送金してみましょう。（ここでは省略しましたが、先と同様送金（eth.sendTransactionコマンドの実行）の前に送金元のアカウントのロック解除を行う必要があります。）

```
> eth.getBalance(eth.accounts[1]) //保有額を確認。最初に送金された 5 ether を保有している。
'5000000000000000000'
> 
> eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[0], value: web3.toWei(3, "ether")}) // 3 ether を'0x24afe...'に送金。
'0x5fd0bdcccb379a8b4034668464ad9a499a8a6b7801ed66ac23e4df3d67ec64a5'
>
> eth.getBalance(eth.accounts[1]) // 送金後の保有額を確認。 5 - 3 = 2 ether のはずが・・・・
'1998825500779091000'
```

5 ether 保有していた状態から、3 ether 送金したため、'0x59c44...' のアカウントの ether保有額は 2 ether と予想されるのですが、実際には 2 ether よりも小さい額になっています。

実は、この送金額以上に引かれた差額分（1,174,499,220,909,000 wei)がトランザクションを生成した際に採掘者に対して支払うトランザクション手数料となっており、採掘者の報酬に加えられます。

## トランザクション情報を調べる。

ここで、トランザクションについてもう少し詳しく調べてみましょう。トランザクションの情報は`eth.getTransaction(tx_id)`コマンドで調べることができます。先ほど行った`accounts[1]`のアドレスから 3 ether 送金した際のトランザクションの情報を見てみます。パラメーター、`tx_id`には、送金実行時に返されたトランザクションIDを指定します。

```
> eth.getTransaction('0x5fd0bdcccb379a8b4034668464ad9a499a8a6b7801ed66ac23e4df3d67ec64a5')
{
  blockHash: '0xeef0f74bc51ecb9f3d64099fa4f3c1651af36a632380d41dd987e8e7064a5276',
  blockNumber: 11076,
  from: '0x868d840e872df5134a3be6f7b68e52cb680fe3ac',
  gas: 90000,
  gasPrice: '55928534329',
  hash: '0x5fd0bdcccb379a8b4034668464ad9a499a8a6b7801ed66ac23e4df3d67ec64a5',
  input: '0x',
  nonce: 0,
  to: '0x2efbdc840746c862b63077643e5b7dd8bebb8448',
  transactionIndex: 0,
  value: '3000000000000000000'
}
```

主な項目について簡単に見ていきましょう。

* `blockHash` & `blockNumber`：このトランザクションを含んだブロックのヘッダ・ハッシュとブロック高を示しています。まだこのトランザクションを含んだブロックが採掘されていないときには、これらのフィールドは空の状態で表示されます。
* `gas`：トランザクションの処理時のgasの使用量の「最大値」を示しています。（実際のトランザクション処理時のgasの使用量ではないので、注意してください。実際にトランザクション処理時に使用されたgasの量を知る方法は下記のTIPを参照ください。）
* `gasPrice`：トランザクションの処理時に採掘者に支払う1 gas 当たりの手数料（wei）を示しています。
* `from` & `to` & `value`：それぞれ、トランザクションにより送金する送金元、宛先、送金額（wei）を示しています。

### TIP

上記のようにトランザクション情報で表示される`gas`の量は、トランザクションの処理時に許容する「最大」gas使用量を示していました。では、実際に今回のトランザクションにどれだけのgasを使用したのかを知るためにはどうしたらよいのでしょうか？今回のトランザクションの手数料は先に書いたとおり、1,174,499,220,909,000 wei でした。またトランザクションの情報から1 gas 当たりの手数料`gasPrice`は 55,928,534,329 wei と分かるので、実際に今回のトランザクションで使用したgasの量は、(1,174,499,220,909,000 / 55,928,534,329) = 21,000 となり、 21,000 gas が使用されたことがわかります。

## 脚注


# スマートコントラクトを作成し実行する

Ethereumは分散アプリケーション・プラットフォームです。Ethereumにおいて分散アプリケーションは、単一のスマートコントラクト、または複数のスマートコントラクトが連携して実現されるものとなっています。この章では最も単純なスマートコントラクトを作成し、それを動作させる手順を追うことで、スマートコントラクトとは何か、どのようにスマートコントラクトを作成しデプロイするのか、そしてどのようにスマートコントラクトを利用するのかを見ていきます。

## スマートコントラクトとは

先に述べたように、Ethereumには２つのタイプのアカウント、つまりEOA（Externally Owned Account）とContractが存在します。Ethereum上でスマートコントラクトの実態はContractアカウントです。

JavaやPythonなどオブジェクト指向言語になじみがある人であればContractアカウントは、オブジェクト指向言語での「クラス」に似たものと考えるとイメージがつかみやすいかもしれません。それぞれのContractは、各自にクラス変数に相当するような、内部状態を保持するストレージ部分と、メソッドに相当するような、実行コードである「コントラクト・コード」を持っています。

[「etherを送金する」](https://book.ethereum-jp.net/first_use/sending_ether.html)節で見たように、EOAが、他のEOAのアドレスを宛先としたトランザクションを生成することで、他のEOAに対してetherを送金することができました。同様にEOAがContractアカウントのアドレスを宛先とするトランザクションを生成することも可能です。この場合、EOAを宛先とした場合と同様にContractアカウントへのetherの送金も可能ですが、同時にコントラクト・コードの実行を指示することが可能です。

コントラクト・コードに任意の動作をプログラムすることで、独自通貨の発行や投票システムなどの様々なアプリケーションが実現できます。コントラクト・コードの実行は採掘者によって行われ、実行結果は公開元帳であるブロックチェーンに書き込まれていき、特定の中央機関なくアプリケーションが動作していきます。

## Solidity

コントラクト・コードは、Ethereumネットワーク上で「Ethereum Virtual Machine Code」または略して「EVM Code」と呼ばれるバイトコードの形式で記述され処理されます。 このようなバイトコードの形式は低水準の機械言語であって、人間にとっては可読性が悪く、また開発の生産性も悪いものとなっています。

そこでEthereumでは、コントラクト・コードを記述することに特化した可読性の高い高水準言語と、それを EVM Code に翻訳するためのコンパイラが幾つか開発されています。

その代表的なものとして「Solidity」が挙げられます。Solidityは Java Script に似た構文をもつ言語です。

ここでは、ContractをこのSolidityを使って開発していくものとして、まずは、Solidityのコンパイラである「solc」を準備しましょう。

## Solidityコンパイラ（solc）のインストール

まず、システムへsolcのインストールを行います。solcのインストールは、Gethのコンソールから抜けてそれぞれのプラットフォーム（OS）のコンソール上で行います。

#### Ubuntuへのインストール

以下のコマンドを実行してください。

```bash
$ sudo add-apt-repository ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install solc
```

以下のコマンドでsolcのバージョン情報が表示されれば問題なくインストールされています。

```bash
$ solc --version
```

#### Mac OS Xへのインストール

以下のコマンドを実行し、cpp-ethereumをインストールしてください 。Mac OS Xへのインストールには、[Homebrew](http://brew.sh/) が事前にインストールされている必要があります。

```bash
brew update
brew upgrade
brew tap ethereum/ethereum
brew install solidity
brew linkapps solidity
```

以下のコマンドでsolcのバージョン情報が表示されれば問題なくインストールされています。

```bash
$ solc --version
```

また、以下のコマンドを実行し、その結果に表示されるsolcへのパスをメモしておいてください。Gethとsolcをリンクさせるために後ほど利用します。

```bash
$ which solc
```

#### Windowsへのインストール

[このページ](http://solidity.readthedocs.io/en/latest/installing-solidity.html)の手順を参考にインストールしてください。&#x20;

## スマートコントラクトの作成から実行までの流れ

コンパイラsolcのインストールが完了し、最初のスマートコントラクトを作成する準備が整いました。スマートコントラクトを作成し、それにアクセスし実行するまでの流れは次のようになります。 1. コントラクト・コードの作成

* Solidity言語でスマートコントラクトの内容を記述したコントラクト・コードをプログラミングする。

1. コントラクト・コードのコンパイル
   * コントラクト・コードを、solcを使ってコンパイルする。
2. 「Contract」アカウントを生成
   * コンパイル済みのコードをトランザクションに付加してネットワークに送信する。そのトランザクションを受信した採掘者は、トランザクションをブロックチェーンに登録する。これにより「Contract」アカウントが生成されそのアドレスが発行される。
3. スマートコントラクトへのアクセスと実行
   * スマートコントラクトを実行したいユーザーはContractアカウントへトランザクションを発行することによりスマートコントラクトを実行する。

以上の手順を、最も単純なスマートコントラクトを例に実際に行って行きましょう。

### コントラクト・コードの作成

#### 最も単純なスマートコントラクト（OneNumRegister）

最も簡単なスマートコントラクトとして、複数のユーザーで１つの整数値を登録・更新するスマートコントラクトを作成してみましょう。例えば、ある利用者が「3」を登録すると他の利用者が登録情報を参照した時には「3」が表示され、また別の利用者がその整数値を「10」と更新すれば、他の利用者が登録情報を参照した時には新しい登録内容の「10」が表示されるものです。

非常にシンプルな機能ですが、この登録内容とその更新の整合性を担保するために、通常は何らかの管理のための中央機関やシステムが必要です。しかしEthreumはブロックチェーンの特性を利用することで中央機関の存在しないP2Pのシステムでこの整合性を保つことが可能になるのです。

#### コントラクト・コード

さて、上記のようなContract（SingleNumRegisterと名付けます）は、Solidity言語を使って記述すると以下のコードになります。

```javascript
pragma solidity ^0.4.0;
contract SingleNumRegister {
    uint storedData;
    function set(uint x) public{
        storedData = x;
    }
    function get() public constant returns (uint retVal){
        return storedData;
    }
}
```

Solidityの言語仕様の詳細は後の「コントラクト・プログラミング言語：Solidity」の章で解説します。そのため、今ここで、このコードの意味を全て把握する必要はありません。しかしコードを眺めると大きく以下の特徴があることが見て取れると思います。

* スマートコントラクトの名前は`contract`の宣言で規定されること。
* `storedData`という`uint`型の変数が定義されており、この変数に登録数値が格納されること。
* `set`と`get`の２つの関数が定義されていること。
  * setという名前の関数は、引き渡されたパラメータの内容で、storedData変数が更新すること。
  * getという名前の関数は、登録されているstoredData変数の内容を返却すること。

このコードを記載したファイルを適当なディレクトリ上で「SingleNumRegister.sol」の名前で保存します。

### コントラクト・コードのコンパイル

上記のソースコードを先にインストールしたsolcコマンドを用いて下記のようにコンパイルします。実行結果としてプロンプト上に`Binary`と`Contract JSON ABI`が表示されます  。

```
$ solc --abi --bin SingleNumRegister.sol　//ソースコードをコンパイル

======= SingleNumRegister.sol:SingleNumRegister =======
Binary:
6060604052341561000f57600080fd5b60d38061001d6000396000f3006060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c14606e575b600080fd5b3415605857600080fd5b606c60048080359060200190919050506094565b005b3415607857600080fd5b607e609e565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820bdd0549ef41e9c70cc944a6c19e54da47ecda63a1c5edfc7024125b5c49b4acb0029
Contract JSON ABI
[{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
```

### 「Contract」アカウントを生成

コントラクト・コードのコンパイルは完了しましたが、コンパイルしたコードはContract作成者のノード上にあるだけで、まだEthereumネットワーク内の誰もこのContractにアクセスできません。このコンパイル済みコードをEthereumネットワークに送信し、採掘者によってブロックチェーンに登録してもらって初めて他のユーザーがこのContractにアクセス出来るようになります。

EOAからトランザクションを生成し送信することで、作成したContractをEthereumネットワークに送信できます。gethを起動し、geth上のプロンプトでまず、先ほどのコンパイル結果を適当な変数に格納します。

```javascript
> var bin = "0x6060604052341561000f57600080fd5b60d38061001d6000396000f3006060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c14606e575b600080fd5b3415605857600080fd5b606c60048080359060200190919050506094565b005b3415607857600080fd5b607e609e565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820bdd0549ef41e9c70cc944a6c19e54da47ecda63a1c5edfc7024125b5c49b4acb0029"
> var abi = [{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
```

さらに続けて、これらの変数を用いて下記のコマンドを実行します。

```javascript
> var contract = eth.contract(abi)
> var myContract = contract.new({ from: eth.accounts[0], data: bin})
```

詳細は「コントラクト・プログラミング言語：Solidity」の章で解説しますが、上記のコマンドの1行目でContractのオブジェクトを生成し、2行目で、そのオブジェクト情報を含んだトランザクションをEthereumネットワークに送信しています。そして、ここで`myContract`が「Contract」アカウントを示すオブジェクトになります。

採掘者はこのトランザクションを受信し、このContractを登録したブロックの採掘を行います。その際にContractのアドレスが付加されます。

採掘者が採掘を終える前の`myContract`の内容を表示してみると、

```
> myContract
{
  abi: [{
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }],
  address: undefined,
  transactionHash: "0x902709c68fa91ddd19559301b97adb17ed602deb9f8f3a44f48efc2d667fb2aa",
  allEvents: function(),
  get: function(),
  set: function()
}
```

のように、myContractのアドレスが未定になっています。ここで、transactionHashは今回のトランザクションのIDです。しばらくして採掘が成功すると、

```
> myContract
{
  abi: [{
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }],
  address: "0x7a28373a596a5e0dc7074aeec2c02e4f2413cf34",
  transactionHash: "0x902709c68fa91ddd19559301b97adb17ed602deb9f8f3a44f48efc2d667fb2aa",
  allEvents: function(),
  get: function(),
  set: function()
}
```

のように、contractのアドレス（`'0x7a28373a596a5e0dc7074aeec2c02e4f2413cf34'`）が付加されています。これで、作成したスマートコントラクトがEthereumネットワーク上にアドレス`'0x7a28373a596a5e0dc7074aeec2c02e4f2413cf34'`のContractアカウントとして登録されたことになります。

## 「Contract」アカウントへのアクセス

登録されたContractアカウントの情報を参照したり、トランザクションを発行することで、今回作成したスマートコントラクトを実行することが可能になります。今回のスマートコントラクトは、スマートコントラクト1つの整数値を任意のユーザーが登録・更新できるものでした。作成者であるあなたは、このスマートコントラクトを他のユーザーにも利用してもらいたいと考えたとき、どのようにすればよいのでしょうか。

他のユーザーに自身の作成したスマートコントラクトを利用してもらうためには、以下の2種類の情報を他のユーザーに伝える必要があります。

**Contractのアドレス：**

スマートコントラクトにアクセスするために、その実態であるContractアカウントのアドレスが必要となります。今回のContractでは`'0x7a28373a596a5e0dc7074aeec2c02e4f2413cf34'`が付加されていました。

**ContractのABI (Application Binary Interface) ：**

ABIとはContractの取り扱い説明書のようなものです。例えば、このContractがどのような名前の関数が定義されているか、それぞれの関数にアクセスするために、どのような型のパラメータを渡す必要があるか、関数の実行結果はどのような型のデータが返るか、などの情報が含まれたものです。今回のスマートコントラクトでは、Contractアカウント生成時に`myContract`の変数に格納された情報の中の`abi`属性です。実際に`myContract.abi`の内容を表示してみると以下のとおりです。Contract内に定義された関数の引数や戻り値などの情報が記述されているのが見て取れます。

```
> myContract.abi
[{
      constant: false,
      inputs: [{...}],
      name: "set",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "get",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }]
```

この、ContractアカウントのアドレスとABIの２つの情報があれば、他のユーザーは、あなたの作ったスマートコントラクトにアクセスができます。Contractアカウントへアクセスするオブジェクトは以下の書式で生成できます。

```
eth.contract(ABI_DEF).at(ADDRESS);
```

ここで、`ABI_DEF`、`ADDRESS`を今回のContractのものに置きかえます。今回はそれぞれ変数`myContract.address`、`myContract.abi`に既に格納されているためそれを利用します。

```
var cnt = eth.contract(myContract.abi).at(myContract.address);
```

このオブジェクト`cnt`を用いてContractにアクセスをします。Contractの状態を変更する場合、つまり今回のContractでset関数でContractに登録された整数値を変更する場合は、トランザクションを生成することでアクセスします。このトランザクションは採掘者によりブロックチェーンに登録されることで、トランザクションの発生と、それによるContractの状態の変化についてEthereumネットワーク内で合意形成されることになります。

Contractの登録値を「6」に変更するトランザクションは以下のコマンドで送信できます。ここで`set`はコントラクト・コード内で定義した登録値を更新する関数の関数名です。このコマンドを実行した際の戻り値はトランザクションIDです。

```
> cnt.set.sendTransaction(6,{from:eth.accounts[0]})
'0x979c4e413a647673632d74a6c8b7f5b25a3260f3fefa4abea2dc265d61215939'
```

このトランザクションとその結果の状態が採掘者によりブロックチェーンに登録されると、Contractの登録整数値は「6」に更新されます。&#x20;

では、このContractに登録されている最新の登録整数値を参照する場合はどうすればよいでしょうか？Contractの状態を参照する際は、状態を変更しそれをEthereumネットワーク内で同意を形成する必要はないため、トランザクションを送信する必要はありません。下記のように参照の関数（今回は`get`）を単純に呼び出すことで参照が可能です。

```
> cnt.get()
'6'
```

ここまで、Ethereumで行う「採掘」「送金」「Contractの生成と利用」についての大まかな手順を見てきました。これまでは自分個人だけが参加するテスト・ネットでこれらの機能を確認してきました。次の節では、多数の参加者が参加している、本番のEthereumネットワーク（ライブ・ネット）に接続して行きます。

### 脚注


# メインネットに接続する

## メインネット（Mainnet）に接続する

2015年7月30日にFrontierがリリースされ、Ethereumは本番ネットワーク（メインネット）の運用が開始されました。今後、Ethereumのブロックチェーン等のインフラを利用した分散アプリケーションは、このメインネット上にてスマートコントラクトが登録され動作していくことになります。本書ではここまで、個人用のテスト用のネットワーク（テスト・ネット）に繋いで、Gethクライアントを実際に操作しながらEthereumの概観を説明してきました。この節では実際にメインネットに接続していきます。

## メインネットへの接続

メインネットに接続する際のデータ用ディレクトリを事前に用意しておきます。

```bash
$ mkdir /home/ubuntu/mainnet_data
```

以下のコマンドを実行してメインネットに接続します。

```bash
$ geth --datadir "/home/ubuntu/mainnet_data" 2>> /home/ubuntu/mainnet_data/e01.log &
```

テスト・ネットに接続した際のコマンドとの違いは、`--networkid`、`--nodiscover` と `--genesis` のオプションを付加していないことになります。

## 接続状況を確認する

上記方法でgethの起動を行うとgethはEthereumのメインネットに接続している他のノードを探索し始め、見つけたノードから順次、P2P接続を開始し始めます。Gethのコンソールを立上げ`net.peerCount`コマンドを実行すると、自分のノードが他のいくつのノードと接続されているかを表示することが出来ます。（探索時間がかかるため起動から数分から十数分程度掛かるので注意ください。）

```
> net.peerCount
25
```

また、実際に接続されているノードの情報は`admin.peers`のコマンドで確認することが出来ます。

```
> admin.peers
[{
  Caps: 'eth/60, eth/61',
  ID: '99017abe7031b48a855b8e79fecb6c927cda88229354f21184d343941ae78ee261d0ccb9f9999f620f96bd729b2cb7c4e8cdf3218d71b016fe531ff439b81dcc',
  LocalAddress: '160.16.80.199:34057',
  Name: 'Geth/v1.0.2/linux/go1.4.2',
  RemoteAddress: '192.169.7.150:30303'
}, 
（中略）
{
  Caps: 'eth/60, eth/61',
  ID: '6f8c6cc4a878ed88e03c7a0ee01386e095fbc1bfd48352c7bec05142cc60795317b5b8c5e9afc9863a414541df4d5b1627a86418177857166171fd45497c75ab',
  LocalAddress: '160.16.80.199:41617',
  Name: 'Geth/v1.0.2/linux/go1.4.2',
  RemoteAddress: '83.77.31.183:30303'
} ]
>
```

## メインネット上での操作

メインネットで接続した`geth`上で、これまでに示した採掘や送金、スマートコントラクトの作成方法等の手順を行うことでメインネットでの操作が可能になります。ただし以下のことに注意してください。

* 採掘を始めるとまずメインネットでのブロックチェーン情報との同期が始まります。これは環境にもよりますが数日かかるものになります。
* ブロックチェーン情報は現在数ギガバイトのオーダーの容量となり今後も増え続けます。そのため`geth`起動時の`--data-dir`オプションで指定するディレクトリは容量の大きい領域（パーティション）内のディレクトリを指定することを推奨します。


# Contract開発環境（IDE）の活用

前節までで、gethを用いてコマンドライン上でSolidity言語によるContractの作成からコンパイル、そして実行までを行う手順を見てきました。しかしこれらは見てきたように煩雑な操作が必要で、Solidity言語を用いてContractを実際に試行錯誤でコーディングしていくには不適です。そのため、Contractのコーディングとコンパイル及び実行を助ける幾つかの開発環境が開発され始めています。この節では、これらの中の一つの「[Remix-ide](https://github.com/ethereum/remix-ide)」（以下Remix-ide）の使い方を解説します。

[Remix-ide](https://github.com/ethereum/remix-ide)はSolidity言語の開発者の一人である[chriseth](https://github.com/chriseth)により開発されているSolidity言語用Contract開発環境（IDE）であり、Webブラウザ上で

* Contractのコーディング
* コンパイル
* 実行
  * ブロックチェーン上への登録
  * Contract上の関数の実行

が可能です。

## Remix-ideのダウンロードと起動

Remix-ideは以下のようにnpmを用いてインストールします。 remix-ideコマンドで起動したあとに、ブラウザで[ローカルホストの8080番ポート](http://127.0.0.1:8080)にアクセスすることで開くことができます。

```
$ npm install remix-ide -g
$ remix-ide
```

リポジトリから直接cloneする方法もあります。

```
$ git clone https://github.com/ethereum/remix-ide.git
$ cd remix-ide
$ npm install
$ npm run setupremix  
$ npm start
```

実際にRemix-ideをブラウザで開いた画面を下図に示します。画面は大きく左右２つに分かれています。左側はSolidity言語のコードエディタになっており、右側はそのContractの各種情報の表示や実行実行等を行う画面になっています。 ![](/files/-M41_KCLhLTvm9ohCbMw)

Remix-ideは作成されたContractを２通りの方法方で実行することが可能です。これらの方法は、画面右の箱型のタブを押下して現れるラジオボタン「Java Script VM」と「Web3 Provider」で切り替えることが出来ます（下図）。

* **Java Script VM**： ブラウザ上での疑似実行モード。実際のEthereumノードには接続せず、ブラウザ上のJavascript VM 上でContractの関数を疑似的に実行します。
* **Web3 Provider**： Blockchain上での実行モード。実際のEthereumノードに接続し、作成したContractをブロックチェーン上に登録した上でContractの関数を実行します。

次の節から後者のWeb3 Providerのモードでの実行手順を見ていきます。

![](/files/-M41_KCRcSvYfUietLhe)

## Remix-ideとEthereumノードを接続する。

Remix-ideから作成したContractを実際のBlockchainに登録したりBlockchain上のContractを実行したりするためには、まずRemix-ideとEthereumノードを接続する必要があります。

### gethの起動

これまでのようにコマンドラインからgethを起動しテストネットに接続します。下記のコマンドを実行します。

```
$ geth --networkid "10" --nodiscover --datadir "/home/test_u/eth_private_net" --mine --unlock 0xa7653f153f9ead98dc3be08abfc5314f596f97c6 --rpc --rpcaddr "192.168.5.6" --rpcport "8545" --rpccorsdomain "*" console 2>> /home/test_u/eth_private_net/geth_err.log
```

ここで、幾つか新しいコマンドオプションが出てきました。Remix-ideとノードの接続には、gethのRPC（Remote Procedure Call）のAPI機能を利用するのでその設定をコマンドオプションで行っています。

* `--rpc`：gethのRPCサーバとしてのAPIを有効化します。
* `--rpcaddr "192.168.5.6"`:読者の環境に合わせてgethノードのIPアドレスを指定します。Remix-ideとgethを同じPC上で利用するなら "127.0.0.1"か"localhost"を指定します。
* `--rpcport "8545"`： RCP APIのポート番号を指定します。（特に問題なければデフォルトの8545を指定すればよいです。）
* `--rpccorsdomain "*"`： クロスドメインアクセスを許可するドメイン。ここでは任意のドメインを許可しています。

また、以下のオプションも加えています。

* `--mine`：gethの起動と同時に採掘を開始するオプション
* `--unlock 0xa7653f153f9ead98dc3be08abfc5314f596f97c6"`: 指定されたアドレスのアカウントのロックを解除します。読者の環境に合わせて、coinbaseのアドレスを指定してください。（起動時にパスワードが求められます。）

### Remix-ideからノードに接続

前述のようにRemix-ideをブラウザで開きます。下図のように、Contractを入力した後画面右側の箱形のアイコンのタブを選択し「Web3 Provider」のラジオボタンを選択します。また「Web3 Provider Endpoint」のテキストボックスにはgethの起動時に指定したrpcaddrとrpcportを組み合わせて「[http://rpcaddr:rpcport](http://rpcaddr/:rpcport) 」の形式で指定します。（ここの例では[http://192.168.5.6:8545）](http://192.168.5.6/:8545）)

画面右下などに接続エラー等が表示されなければ、gethとのrpcでの接続が成功しています。

![](/files/-M41_KCTOaic-zs-rrxZ)

### Contractの作成・ブロックチェーンへの登録・実行

画面左側のエディタでContractを作成します。ここでは例として「Contractを作成する」節で使用した「SingleNumRegister」Contractコードを左側のコード・エディタ部分に入力します（下図左）。コードを入力し終えたら右側の赤色のCreateボタンを押下します。Remix-ideは指定されたEthereumノードにアクセスしブロックチェーン上にContractを登録するためのTransactionを発行します。しばらくして（数秒～十数秒）Ethereumネットワーク上でTransactionが採掘されると今回のContractのブロックチェーン上でのアドレスとContractで規定された関数（ここではgetとsetの関数）が表示されます（下図右）。

![](/files/-M41_KCVK1qadAjqmUU4)

実際にset関数のテキスト入力エリアに正の整数値、例えば「136」を入力し赤色のいるset関数実行ボタンを押下するとbrouser-solidityはトランザクションを発行しEthereumネットワーク上で採掘されるとトランザクション実行結果が表示されます。またそのあと青色のget関数ボタンを押下すればset関数で設定した正の整数が表示されることになります。

#### 脚注

[This work](http://book.ethereum-jp.net/) is licenced under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).


# Meteorを用いた分散型アプリケーション開発

これまでにEthereumはP2Pシステム上で動作する次世代分散型アプリケーション（Dapp）のプラットフォームである、という話をしてきました。 ここからは、実際にEthereum上で動作する分散型アプリケーションを開発していく手順をチュートリアル形式で見ていきます。本節ではJavascript言語のアプリケーションフレームワークである「Meteor」を利用してDappの開発を進めていきます。


# Meteorを準備する

## Meteorとは

まずは今回の開発にフレームワークとして利用するMeteorについて説明していきます。

[Meteor](https://www.meteor.com/)はオープンソースのWebアプリケーション・フレームワークであり、2012年に最初のリリースが行われて以降、精力的に機能強化が行われています。現在ではWebブラウザ上での動作はもちろん、iOSアプリやAndoroidアプリとして動作するアプリケーション開発も可能になっています。アプリケーション開発における生産性を高める機能が数多く備わっており、リリース以来多くの注目を集めています。Meteorには大きく以下の３つの特徴があります。

* **UNIVERSAL JAVASCRIPT**： Meteorではクライアント側とサーバ側のコードの両方をJavascript言語で記述することを可能にしています。またクライアント側もWebブラウザ/iOSアプリ/Androidアプリに関わらずJavascript言語でのアプリケーション動作の記述を可能にすることで、完全に統一されたコードの管理が可能になり、コードの共用など開発及び保守のコストが軽減されます。
* **Realtime & Reactive**： Webアプリケーションの使用者の中の誰かがサーバ側のデータを更新すると、その変更がリアルタイムにアプリケーションを利用している全てのユーザーに伝搬し「再読み込み」のようなユーザーの操作もなく画面に自動的に反映される、といったリアルタイム、かつリアクティブなWebアプリケーションの開発を非常に容易にする仕組みが用意されています。
* **Develop to Deploy**： Meteorは開発だけでなくアプリケーションの公開までも非常に容易にします。開発者が独自にサーバを用意しアプリケーションのデプロイと公開を行うこともできますが、MeteorはMeteorを使って開発したアプリケーションの公開用プラットフォームを用意しており、コマンド一つで自分のアプリケーションをWeb上に公開することが可能にしています。

Meteorのこのような特長に加え、既にEthereumのノードとAPI連携するためのライブラリ群（Meteorではパッケージと呼びます）が開発されており、これらを組み込むことでP2PのEthereumネットワーク上で動作するDappの開発が可能になります。実際にEthereumの公式walletである[Mist](https://github.com/ethereum/mist)もMeteorを利用して開発されています。

分散型アプリケーションの開発を進めていく準備として、先ずはMeteorインストールしてみましょう。以下特に言及しない場合はubuntu 14.04の環境を前提とします。他のOSの場合には適宜読み替えてください。（Linux OSやMac OSの場合はほぼ同じ操作で進められるでしょう。）

## Meteor事始め

### Meteorのインストール

Meteorのインストールは極めて簡単です。ターミナルを開き

```bash
$ curl https://install.meteor.com | sh
```

の１行のコマンドを実行するのみです。実行の途中でsudoのパスワードを聞かれるので適宜入力してください。実行後

```bash
$ meteor --version
```

と入力してバージョン情報が表示されればインストールが出来ています。

### 最初のアプリケーションを作成する

Meteorのインストールしたので、実際にMeteorで簡単なアプリケーションを作ってみます。そのために、任意のディレクトリ上で

```bash
$ meteor create myfirstapp
```

のコマンドを実行します。ここで`myfirstapp`は今回作るアプリケーション名です。このコマンドを実行すると、

```
myfirstapp.css
myfirstapp.html
myfirstapp.js
```

の３つのファイルと`.meteor`ディレクトリが含まれる`myfirstapp`のディレクトリが作成されます。これはmeteorが自動的に作成するアプリケーションのひな形（boilerplate）です。このディレクトリのファイルを編集したり、必要に応じて追加していくことでMeteorのWebアプリケーションの開発を進めていくことになります。この作成されたひな形は（至極単純なものですが）実際にWebアプリケーションとして動作するので、動かしてみましょう。

を`myfirstapp`ディレクトリに移動して

```bash
$ meteor
```

コマンドを実行します。実行するとしばらくしてコンソールに`=> App running at: http://localhost:3000/`と表示されるのでWebブラウザでアドレスに「<http://localhost:3000/> 」と入力しアクセスします。すると下図のような（単純な）Webアプリケーションが表示されます。

![](/files/-M41_ICoLLhH-6q_wAUd)

以上、Meteorのインストールからひな型の作成とその実行までを見てきました。次節以降でこのMeteorを用いたEthereumネットワーク上で動作する分散型アプリケーションの開発の方法をチュートリアル形式で見ていきます。&#x20;

#### ■TIPS

Meteorの特徴として、「Meteorで開発したWebアプリケーションをコマンド一つで世界に公開できる」というものがあります。公開は作成したアプリケーションのディレクトリで例えば

```bash
$ meteor deploy hogehoge
```

のコマンドを実行するだけです。開発したアプリケーションが自動で公開サーバにアップロード・デプロイされWeb上で公開されます。ここで`hogehoge`の部分で公開する際のURLのサブドメインを指定しています。この場合URL「<http://hogehoege.meteor.com> 」で開発したアプリケーションにアクセスできるようになります。

## Meteorをさらに知るために

次節以降で、Meteorを用いた「Ethereumネットワーク上で動作するDappの開発」に主眼を置いて解説していきます。そのためMeteor持つ強力な機能の全てを本書内で解説するこはできません。Meteor自体のより詳細で良質な解説を下記に挙げておきます。

* [**Meteor公式チュートリアル**](https://www.meteor.com/tutorials/blaze/creating-an-app)： 簡単なTODO管理アプリケーションの開発をチュートリアル形式で解説しています。
* [**Discover Meteor**](https://www.discovermeteor.com/)： リアルタイムのソーシャル・ニュース・アプリを題材にチュートリアル形式でMeteorとそれを用いた開発を解説した電子書籍です。上記の公式チュートリアルよりもより網羅的です。有料（$29-）でGumroadにより販売されています。また有志による[日本語翻訳版も公開されており](http://ja.discovermeteor.com/)、こちらは無料で閲覧が可能です。
* [**Meteor Docs**](http://docs.meteor.com/#/full/)： 公式のAPIリファレンスです。


# 簡単なEtherのwalletを作る（１）

MeteorによるDapp開発の第一歩として、Ethereumの組み込み通貨であるEtherをアカウント間で送金することができる簡単なwalletアプリ「simple-ether-wallet」を作成してみます。

本章で説明するサンプルアプリのソースコードは[GitHub上](https://github.com/a-mitani/simple-ether-wallet)に公開しています。

今回作成するアプリは、アカウント情報とEthereumネットワーク情報を表示する「ダッシュボード」ビューと、Etherの送金と過去の送金履歴の表示を行う「送金」ビューの２つで構成されます。各情報項目は、ユーザーがブラウザ上で再読み込み等の特別な操作をすることなくEthereumネットワーク上での最新の情報が自動的に更新されていくリアクティブな動きをします。

本節では「ダッシュボード」ビューの部分を実装することで、Meteorの使い方とEthereum関連のパッケージの使い方に慣れることを目標にします。「送金」ビューについては次節以降で実装していきます。

![](/files/-M41_ICkKARoDoars-G6)

【simple-ether-walletのダッシュボードビュー】

![](/files/-M41_ICmZInr4SbEoHbt)

【simple-ether-walletの送金ビュー】

## gethの起動（RPCの有効化）

まず下準備として、今回作成するwalletからの接続を受けるように下記のコマンドでgethを起動しておきます。ここではネットワークIDが10のテストネットに接続しています。本格的にDappを公開するまではテストネットにて動作を確認するほうが良いでしょう。

```bash
$ geth --networkid "10" --nodiscover --datadir "/home/test_u/eth_private_net" --mine --unlock 0xa7653f153f9ead98dc3be08abfc5314f596f97c6 --rpc --rpcaddr "192.168.5.6" --rpcport "8545" --rpccorsdomain "*" console 2>> /home/test_u/eth_private_net/geth_err.log
```

上記コマンドは幾つか新しいコマンドオプションを追加しています。今回作成するDappとノードの連携はGethのRPC（Remote Procedure Call）のAPI機能を利用するのでその設定をコマンドオプションで行っています。

* `--rpc`：gethのRPCサーバとしてのAPIを有効化します。
* `--rpcaddr "192.168.5.6"`:読者の環境に合わせてgethノードのIPアドレスを指定します。ローカル環境で試験を行うなら、"127.0.0.1"か"localhost"を指定することも可能です。
* `--rpcport "8545"`： RCP APIのポート番号を指定します。（特に問題なければデフォルトの8545を指定すればよいです。）
* `--rpccorsdomain "*"`： クロスドメインアクセスを許可するドメイン。ここでは任意のドメインを許可しています。

また、以下のオプションも加えています。

* `--mine`：gethの起動と同時に採掘を開始するオプション
* `--unlock 0xa7653f153f9ead98dc3be08abfc5314f596f97c6"`: 指定されたアドレスのアカウントのロックを解除します。読者の環境に合わせて、coinbaseのアドレスを指定してください。（起動時にパスワードが求められます。）

**■■ TIP ■■**

gethのconsoleを利用せずバックグラウンドでgethを起動しておくと毎度gethを起動する手間が省けて便利です。その場合は 1. 上記コマンドの`console`のオプションを外したコマンドを実行 2. プロンプト上でパスワードを聞かれたら、入力。 3. ［Ctrl］＋［Z］キーを押下しプロセスを一時停止 4. `bg`コマンドを実行し、プロセスをバックグラウンド実行に移行

の手順で行えばよいでしょう。

## Wallet用のMeteorプロジェクトを作成

Meteorをインストールした環境で適当なディレクトリに、今回作成するsimple-ether-walletのMeteorプロジェクトを作成します。

```bash
$ cd ~/eth-meteor-proj # 任意のディレクトリに移動
$ meteor create simple-ether-wallet # 新しいMeteorプロジェクトを作成
```

「Meteorを使ってみる」節と同様に、この初期状態のWebアプリで念のためアクセス可能かを確認してみます。上記コマンドを実行して新しく作成された`simple-ether-wallet`ディレクトリ（以下、プロジェクトRoot）に移動して

```bash
$ meteor
```

コマンドを実行します。実行するとしばらくしてコンソールに`=> App running at: http://localhost:3000/`と表示されるのでWebブラウザでアドレスに「<http://localhost:3000/> 」と入力しアクセスします。すると下図のような（単純な）Webアプリケーションが表示されます。

![](/files/-M41_ICoLLhH-6q_wAUd)

起動して画面が表示されることが確認できたら、デモ用の余分なコードを削除して行きます。まず、プロジェクトRoot直下の`server`ディレクトリを内部のファイルごと削除します。また、`client`ディレクトリ内の`main.js`内の記述を全て削除し空ファイルの状態にします。そして`main.html`ファイルは下記のコードに書き換えます。

> main.html

```markup
<head>
  <title>Simple Ether Wallet</title>
</head>
<body>
  <h1> Hello, world!!</h1>
</body>
```

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step001")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step001)

この状態でWebアプリケーションにアクセスすると、下図のような画面が表示されるはずです。 ![](/files/-M41_ICqgoJmT0jWpfVb)

**■■ Meteor TIP ■■**

Meteorにはプロジェクト内のディレクトリ名には下記のルールがあります。

* `server` ディレクトリ以下のファイルは、サーバサイドのみで実行されます。（今回作成するwalletでは全てクライアント(ブラウザ）側で処理を行い、サーバ側の処理を行わないため`server`ディレクトリごと削除しました。）
* `client` ディレクトリ以下のファイルはクライアントサイド（ex.ブラウザ上）のみで実行されます。
* プロジェクト直下のファイル、および、上記以外のディレクトリ以下のファイルはサーバサイドとクライアントサイドの両方で実行されます。

また、静的なコンテンツ、例えば画像データやフォントデータ等は`public`ディレクトリに配置されるのが慣習です。

## Ethereumノードへの接続

### パッケージの追加

Meteorには標準の機能以外の拡張機能をパッケージとしてインストールすることで様々な機能が追加可能です。Ethereumへの接続も、拡張機能としてパッケージを導入することで容易に可能になります。ここでは今後使用する以下の４つのパッケージを追加します。

* **twbs:bootstrap**: CSSフレームワーク「bootstrap」のパッケージ。
* **ethereum:web3**：EthreumノードとRPC接続するためのライブラリが含まれるパッケージ。
* **ethereum:accounts**：ethereum:web3パッケージのラッパーパッケージで、Ethereumのアカウント関連の情報をmeteor上でリアクティブに取得可能にするパッケージ。
* **ethereum:blocks**：ethereum:web3パッケージのラッパーパッケージで、Ethereumのブロックチェーン関連の情報をmeteor上でリアクティブに取得可能にするパッケージ。

プロジェクトRootに移動し下記のコマンドを実行します。

```bash
$ meteor add twbs:bootstrap 
$ meteor add ethereum:web3
$ meteor add ethereum:accounts
$ meteor add ethereum:blocks
```

**■■ Meteor TIP ■■**

プロジェクトに追加されたパッケージは隠しディレクトリ`.meteor`以下の`packages`ファイルに自動的に記載されます。実際に今回追加した4つのパッケージが`packages`ファイルの末尾に追記されているのを確認してみてください。

### Ethereumノードへの接続

今回追加したパッケージを利用しEthereumノードに接続します。 `client`ディレクトリ以下に`lib`ディレクトリを作成しその下に以下のコードを記述した`init.js`ファイルを配置します。

> client/lib/init.js

```javascript
//Web3インスタンスの生成
web3 = new Web3();

//RPCプロバイダを設定
//URLの部分は読者の環境に合わせてください。（localhostの部分はIPアドレスにて指定してもかまいません。）
if(!web3.currentProvider)
  web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));

// EthAccounts初期化
EthAccounts.init();

//EthBlocksの初期化
EthBlocks.init();
```

この状態でWebアプリケーションを起動してアクセスしてみます。表示される画面は変わらず「Hello, world!!」が表示されますが、アクセス時にブラウザには今回追加したパッケージ及び`init.js`もロードされているためブラウザからEthereumノードにRPCでアクセスが可能になっています。Chromeの開発者ツールのConsoleを起動 し、Ethereumノードに対してアカウントリストを問い合わせる

```javascript
> web3.eth.accounts;
```

のコマンドを実行してみます。 実行結果として

```javascript
["0xa7595f153f9ead98dc3ad08abfc5314f596f97e7", "0xf2057b8aefb9093331faf48f30c1ebeab4ff961d"]
```

のようなアカウントの配列が返されれば、ブラウザからEthereumノードへのアクセスが成功しています。もしこのような結果が返らない場合はgethの起動とそのオプション、アドレスなどを再度確認してください。

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step002")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step002)

**■■ Meteor TIP ■■**

`init.js`ファイルを`client/lib`以下に配置したのは、初期化の処理を今後追加されていくその他の処理よりも先に処理したい理由からです。MeteorではプロジェクトRoot以下のファイルをロードする順序として、`lib`という名称のディレクトリ以下のファイルを最初に読み込むというルールがあるため、今回の`init.js`は例えば`main.html`や`main.js`よりも先にMeteorによりロードされる事になります。Meteorがファイルをロードする順序は[公式ドキュメント（英語）の「File Load Order」節](http://docs.meteor.com/#/full/fileloadorder)に詳細が記載されているので参考にしてください。

## コンポーネントを追加する

### 「Node Status」項目の表示

これまでの作業でブラウザからEthereumノードへの接続が可能になりました。これを利用して画面に「Node Status」項目を表示するようにしていきます。

まずは、`client/main.html`と`client/main.js`ファイルを下記のコードに書き換えます。

> client/main.html

```markup
<head>
  <title>Simple Ether Wallet</title>
</head>

<body>
  <nav class="navbar navbar-default">
    <div class="container-fluid">
      <div class="navbar-header">
        <a class="navbar-brand" href="/">Simple Ether Wallet</a>
      </div>
    </div>
  </nav>

  <main class="container-fluid">
    <div class="row-fluid">
      <div class="col-md-8 col-md-offset-2">
        {{> nodeStatusComponent}}
      </div>
    </div>
  </main>
</body>

<template name="nodeStatusComponent">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4>Node Status</h4>
    </div>
    <table class="table">
      <tbody>
          <tr>
            <th scope="row">Node</th>
            <td>{{currentProvider}}</td>
          </tr>
          <tr>
            <th scope="row">Is Mining?</th>
            <td>{{isMining}}</td>
          </tr>
          <tr>
            <th scope="row">Hashrate</th>
            <td>{{currentHashrate}}</td>
          </tr>
          <tr>
            <th scope="row">Peer Count</th>
            <td>{{currentPeerCount}}</td>
          </tr>
      </tbody>
    </table>
  </div>
</template>
```

> client/main.js

```javascript
//テンプレート「nodeStatusComponent」のテンプレートヘルパー
//web3オブジェクトのプロパティを取得する各種メソッドを定義。
Template.nodeStatusComponent.helpers({

  //接続先ノードの取得
  currentProvider: function(){
    return web3.currentProvider.host;
  },

  //接続先ノードのマイニング状態の取得
  //マイニング中であればtrue、そうでなければfalse
  isMining: function(){
    return web3.eth.mining;
  },

  //接続先ノードのマイニングのハッシュレートを取得
  currentHashrate: function(){
    return web3.eth.hashrate;
  },

  //接続先ノードのピア数の取得
  currentPeerCount: function(){
    return web3.net.peerCount;
  }
});
```

これらのコードを追加することで下図のような、Ethereumノードの状態のテーブルが表示されるはずです。

![](/files/-M41_ICvkP1gVda1vTBY)

ここでは大きく２つ、「テンプレート」と「テンプレートヘルパー」を用いてEthereumノードの状態の取得から表示までを行いました。少しこれらのコードを詳しく見ていきます。

#### ■ テンプレートエンジン：Spacebar

`client/main.html`はおおよそ通常のHTMLファイルの構造と同様ですが、幾つかの部分でMeteor独特の記述が現れています。これはMeteorがテンプレートエンジンとして独自の「[Spacebar](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md)」を採用しており、その構文が含まれていることによります。

Spacebarには主に3種類のタグが規定されています。

1つめはInclusionsタグと呼ばれるもので、`{{> xxx }}`の構文で用います。このタグが配置された場所に、`xxx`の部分で指定された名前と同じname属性を持つ`<template>`タグの内容を挿入する働きをします。今回の`client/main.html`の例では`{{> nodeStatusComponent}}`が、`<template name="nodeStatusComponent">`と`</template>`に囲まれた部分の内容に置き換わることになります。

2つめは「Expressionsタグ」と呼ばれるもので`{{xxx}}`の構文で用います。現在のオブジェクトの属性値か、またはすぐ後に後述するテンプレートヘルパーの関数の戻り値に置き換わる働きをします。今回の `client/main.html` の例では`{{isMining}}`は `client/main.js` の`isMining`関数の返り値に置き換わることになります。

最後は「block helpersタグ」と呼ばれるもので`{{#each}}…{{/each}}` や `{{#if}}…{{/if}}`のような構文で用いられるタグで、テンプレート内での処理フローを制御する働きをします。

#### ■ テンプレートヘルパー

`client/main.js`にはテンプレートヘルパーが定義されています。Meteorでは表示とロジックを分離する設計がされており、表示はテンプレートが、そして表示のためのデータの取得や加工などのロジックはテンプレートヘルパーがその役割を担います。

テンプレートヘルパーは`Template.<myTemplate>.helpers(helperObject)`の形式で定義し、ここで`<myTemplate>`の部分にヘルパーが対象とするテンプレート名に置きかえます。また`helerObject`はヘルパー関数が連想配列形式で列挙されたオブジェクトになります。

今回の`client/main.js`の例では対象とするテンプレート名から`Template.nodeStatusComponent.helpers(...)`として定義され引数として、`web3`オブジェクトからノード状態のプロパティを返するため幾つかの関数が定義されています。

### ソースファイルの分離

この後、アカウント情報とブロック情報を表示する2つのコンポーネント（accountStatusComponentとblockStatusComponent）を追加していきます。これらも先のnodeStatusComponentと同様にテンプレートとそのヘルパーをそれぞれ`main.html`、`main.js`に追記しても問題ありませが、ここではコンポーネント毎にソースファイルを分けて管理することで見通しを良くします。

たとえソースファイルを分けても、Meteorは自動的にclientディレクトリ以下のファイルをロードの順序の規則に則って読み込み、それらを連結して1つのソースファイルと同様に扱うため、動作には影響ありません。

ここでは各種表示コンポーネントのファイルは`client/templates/components`ディレクトリ以下に配置し、テンプレート名が`templateName`の場合、`template_name.html`と`template_name.js`というファイル名がつけていくこととします。この慣習に倣ってそれぞれ`main.html`と`main.js`に記述したコードを一部取り出して、以下のファイルを作成します。

【※】`main.html`と`main.js`内の当該コード箇所は削除します。

> client/templates/components/node\_status\_component.html

```markup
<template name="nodeStatusComponent">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4>Node Status</h4>
    </div>
    <table class="table">
      <tbody>
          <tr>
            <th scope="row">Node</th>
            <td>{{currentProvider}}</td>
          </tr>
          <tr>
            <th scope="row">Is Mining?</th>
            <td>{{isMining}}</td>
          </tr>
          <tr>
            <th scope="row">Hashrate</th>
            <td>{{currentHashrate}}</td>
          </tr>
          <tr>
            <th scope="row">Peer Count</th>
            <td>{{currentPeerCount}}</td>
          </tr>
      </tbody>
    </table>
  </div>
</template>
```

> client/templates/components/node\_status\_component.js

```javascript
//テンプレート「nodeStatusComponent」のテンプレートヘルパー
//web3オブジェクトのプロパティを取得する各種メソッドを定義。
Template.nodeStatusComponent.helpers({

  //接続先ノードの取得
  currentProvider: function(){
    return web3.currentProvider.host;
  },

  //接続先ノードのマイニング状態の取得
  //マイニング中であればtrue、そうでなければfalse
  isMining: function(){
    return web3.eth.mining;
  },

  //接続先ノードのマイニングのハッシュレートを取得
  currentHashrate: function(){
    return web3.eth.hashrate;
  },

  //接続先ノードのピア数の取得
  currentPeerCount: function(){
    return web3.net.peerCount;
  }
});
```

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step003")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step003)

### 「Account Balance」「Block Status」項目の表示

次に、ノードに登録されているアカウント情報を表示する「Account Balance」と、Ethereumネットワーク内のブロックチェーンの情報を表示する「Block Status」の２つのコンポーネントを追加します。

まず`client/main.html`にこれらのコンポーネントのテンプレートを呼び出し表示するためのInclusionsタグ`{{> accountBalanceComponent}}`、`{{> blockStatusComponent}}`を追加します。

> client/main.html （一部抜粋）

```markup
（前略）
  <main class="container-fluid">
    <div class="row-fluid">
      <div class="col-md-8 col-md-offset-2">
        {{> accountBalanceComponent}}
        {{> nodeStatusComponent}}
        {{> blockStatusComponent}}
      </div>
    </div>
  </main>
（後略）
```

さらにテンプレートとテンプレートヘルパーも追加します。ここでテンプレートのidは今回追加したInclusionタグと同じものにします。

> client/templates/components/account\_balance\_component.html

```markup
<template name="accountBalanceComponent">
  <div class="panel panel-primary">
    <div class="panel-heading">
      <h4>Account Balance</h4>
    </div>
    <table class="table">
      <thead>
        <tr>
          <th>Name</th>
          <th>Address</th>
          <th>Balance</th>
        </tr>
      </thead>
      <tbody>
        {{#each accounts}}
          {{> accountBalanceItem}}
        {{/each}}
      </tbody>
    </table>
  </div>
</template>

<template name="accountBalanceItem">
  <tr>
    <td>{{name}}</td>
    <td>{{address}}</td>
    <td>{{balance}}</td>
  </tr>
</template>
```

> client/templates/components/account\_status\_component.js

```javascript
//テンプレート「accountStatusComponent」のヘルパー
Template.accountBalanceComponent.helpers({
  //アカウント情報の取得
  accounts: function(){
    return EthAccounts.find({});
  }
});

//テンプレート「accountBalanceItem」のヘルパー
Template.accountBalanceItem.helpers({
  //アカウントの名前の取得
  name: function(){
    return this.name;
  },
  //アカウントのアドレスの取得
  address: function(){
    return this.address;
  },
  //アカウントが持つEtherの残高を取得（単位はEtherで、小数点３ケタまで取得）
  balance: function(){
    var balanceEth = web3.fromWei(this.balance, "ether");
    return parseFloat(balanceEth).toFixed(3);
  }
});
```

> client/templates/components/block\_status\_component.html

```markup
<template name="blockStatusComponent">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4>Block Status</h4>
    </div>
    <table class="table">
      <tbody>
          <tr>
            <th scope="row">Block Number</th>
            <td>{{latestBlockNum}}</td>
          </tr>
          <tr>
            <th scope="row">Block Hash</th>
            <td>{{latestBlockHash}}</td>
          </tr>
          <tr>
            <th scope="row">Miner</th>
            <td>{{latestBlockMiner}}</td>
          </tr>
          <tr>
            <th scope="row">Mined Datetime</th>
            <td>{{latestBlockDatetime}}</td>
          </tr>
      </tbody>
    </table>
  </div>
</template>
```

> client/templates/components/block\_status\_component.js

```javascript
//テンプレート「blockStatusComponent」のヘルパー
Template.blockStatusComponent.helpers({

  //最新のブロック番号の取得
  latestBlockNum: function(){
    return EthBlocks.latest.number;
  },

  //最新ブロックのハッシュ値を取得
  latestBlockHash: function(){
    return EthBlocks.latest.hash;
  },

  //最新ブロックを採掘した採掘者のアドレスを取得
  latestBlockMiner: function(){
    return EthBlocks.latest.miner;
  },

  //最新ブロックの採掘日時を取得
  latestBlockDatetime: function(){
    return unix2datetime(EthBlocks.latest.timestamp);
  }
});
```

ここで、それぞれのヘルパーは、`nodeStatusComponent`のヘルパとは異なり、情報をweb3オブジェクトから取得するのではなく、そのラッパーである`EthAccounts`や`EthBlocks`から取り出しています。これらのラッパー・オブジェクトを利用することで、状態が変わると自動的に表示が更新されるリアクティブな表示が可能になります。

また、`client/templates/components/account_status_component.html`内で`{{#each accounts}}...{{/each}}`のblock helpersタグが追加されています。これはヘルパーでのaccountsメソッドで取得されるのはアカウントオブジェクトの配列であり、その配列の要素づつ取り出し、それを`accountBalanceItem`テンプレート側で`name`や`balance`属性を取得するようにしています。

最後に、`blockStatusComponent`のヘルパ内で、UNIX時間表記で得られる採掘日時を通常の日時表記で表示されるよう`unix2datetime`関数を呼び出しているので、この関数のコードを追加します。

> client/lib/modules/time\_utils.js

```javascript
//UNIX時間を通常の "yyyymmdd hh:mm:ss"フォーマットの文字列に変換
unix2datetime = function (unixtime){
  var date = new Date( unixtime * 1000 );
  var year  = date.getFullYear();
  var month = date.getMonth() + 1;
  var day   = date.getDate();
  var hour  = ( date.getHours()   < 10 ) ? '0' + date.getHours()   : date.getHours();
  var min   = ( date.getMinutes() < 10 ) ? '0' + date.getMinutes() : date.getMinutes();
  var sec   = ( date.getSeconds() < 10 ) ? '0' + date.getSeconds() : date.getSeconds();
  var datetimeString = year + '-' + month + '-' + day + ' ' + hour + ':' + min + ':' + sec ;
  return datetimeString;
};
```

これらが正しく記述されたら、下図のような画面が表示されます。ここで、今回追加した「Account Balance」「Block Status」の項目はリアクティブな表示になっていることを実際に確かめてみてください。採掘が成功するたびにEtherebaseのbalance値やブロック情報の項目が、特に手動でリロードをすることなく自動的に更新されるのが見て取れるはずです。また、ノードに新しいアカウントを作成した際も自動的にアカウント情報が追加更新されることになります。

![](/files/-M41_ID4x5GKyaqM5Yh3)

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step004")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step004)

## 「Node Status」項目をリアクティブな動作にする

最後に「Node Status」の項目をリアクティブな動作をするようにしましょう。Account StatusとBlock Statusは、それぞれ`ethereum:accounts`、`ethereum:blocks`のパッケージを利用したために、特別なことをしなくてもパッケージ側でリアクティブな動作をしてくれました。残念ながら「Node Status」項目で表示するHashrate等はこのようなリアクティブな動作サポートするようなパッケージが用意されていません。そのため自分自身でそのような動作をするよう実装していきます。

基本方針として、「Is Mining?」「Hashrate」「Peer Count」の項目の値を Web3 APIから定期的（1秒間隔）に取得し、取得した値をMeteorのSessionオブジェクトに格納し、画面にはそのSessionオブジェクトの値を表示するということを行います。

MeteorにおいてSessionオブジェクトは、同一セッション内（同じユーザーかつ同じブラウザ・タブ内）でグローバル、かつ、単一（シングルトン）のオブジェクトです。このオブジェクトにはKey-value形式でデータを格納することが可能で、リアクティブなデータストアとして利用可能です。

Sessionオブジェクトを利用するには、コンソール上でプロジェクトRootに移動し、下記のコマンドを実行して`session`パッケージを追加します。

```bash
$ meteor add session
```

これでSessionオブジェクトを利用できるようになりましたので、まずはSessionオブジェクトを初期化する関数（`initSessionVars`）を定義します。

> client/lib/modules/init\_session\_vars.js

```javascript
//Session変数の初期化
initSessionVars = function(){

//Node関連の変数
Session.setDefault('isMining', false);
Session.setDefault('hashRate', 0);
Session.setDefault('peerCount', 0);

};
```

次に、定期的にWeb3 APIから値を取得する関数（`observeNode`）を定義します。`Meteor.setInterval`関数を利用して1秒に1回、Web3 APIの非同期関数で求める値を問い合わせて、APIから返った値を`Session`オブジェクトに格納する処理を行っています。

> client/lib/modules/observe\_node.js

```javascript
var peerCountIntervalId = null;

// 採掘状況を非同期で取得
var getIsMining = function(){
  web3.eth.getMining(function(e, res){
    if(!e)
      Session.set('isMining', res);
  });
};

// HashRateを非同期で取得
var getHashRate = function(){
  web3.eth.getHashrate(function(e, res){
    if(!e)
      Session.set('hashRate', res);
  });
};

// PeerCountを非同期で取得
var getPeerCount = function(){
  web3.net.getPeerCount(function(e, res){
    if(!e)
      Session.set('peerCount', res);
  });
};

observeNode = function(){
  Meteor.clearInterval(peerCountIntervalId);
  peerCountIntervalId = Meteor.setInterval(function() {
    getIsMining();
    getHashRate();
    getPeerCount();
  }, 1000);
};
```

次に、上記で定義した`initSessionVars`関数と`observeNode`関数がWallet起動時に呼び出すコードを`client/lib/init.js`の末尾に追記します。

> client/lib/init.js

```javascript
（前略）
//Session変数の初期化
initSessionVars();

//オブザーバの起動
observeNode();
```

以上で、Walletの起動時から定期的にノードの最新の値を問い合わせて、結果を`Session`オブジェクトに格納する処理が実装されました。次にこれをリアクティブに画面に表示します。これは`nodeStatusComponent`のテンプレートヘルパ内でそれぞれの値の取得先を`Session`オブジェクトからKeyを指定して取得するように変更するだけです。先述の通り`Session`はリアクティブなデータソースであるため、Sessionオブジェクトの値が更新されれば自動的にブラウザ上の表示も更新されるようMeteor側で制御してくれます。

`client/templates/components/node_status_component.js`を下記のコードに書き換えます。（先のコードからの変更点はそれぞれの`return`で返す値だけです。）

> client/templates/components/node\_status\_component.js

```javascript
//テンプレート「nodeStatusComponent」のテンプレートヘルパー
//web3オブジェクトのプロパティを取得する各種メソッドを定義。
Template.nodeStatusComponent.helpers({

  //接続先ノードの取得
  currentProvider: function(){
    return web3.currentProvider.host;
  },

  //接続先ノードのマイニング状態の取得
  //マイニング中であればtrue、そうでなければfalse
  isMining: function(){
    return Session.get('isMining');
  },

  //接続先ノードのマイニングのハッシュレートを取得
  currentHashrate: function(){
    return Session.get('hashRate');
  },

  //接続先ノードのピア数の取得
  currentPeerCount: function(){
    return Session.get('peerCount');
  }
});
```

以上の変更を行った上で再度Webアプリの動作を確認すると、「Node Status」の部分もリアクティブな表示が実現していることが確認できるはずです。特に「Hashrate」項目は１秒ごとにめまぐるしく変わっていくのが見て取れるでしょう。

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step005")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step005)

## 脚注


# 簡単なEtherのwalletを作る（２）

前節で「simple-ether-wallet」のダッシュボード部分の実装を行ってきました。本節では「Send」ビューを追加しアカウント間でのEtherの送金を可能にしていきます。

※前節に続きここで説明するアプリケーションのソースコードは[GitHub上](https://github.com/a-mitani/simple-ether-wallet)に公開しています。

## URLルーティング

まず、DashboardとSendの２つのビューそれぞれにURLをマッピングし、リクエストされたURLに応じてどのビューを表示するかをコントロールするURLルーティングの仕組みを導入します。MeteorではURLルーティングに「iron:router」パッケージを利用するのが最も一般的のため、ここでもそれに倣います。コンソール上でプロジェクトRootに移動し下記のコマンドを実行することでパッケージがインストールされます。

```bash
$ meteor add iron:router
```

iron:routerを用いたURLルーティングは、Layoutテンプレートと呼ばれるサイト全体で共通のテンプレートの中にInclusionsタグの一種`{{> yield}}`を埋め込み、iron:routerが自動的にリクエストURLにマッピングされたテンプレート（Routeテンプレート）を`{{> yield}}`部分に埋め込み表示する動作をします。

![](/files/-M41_JJc_uYYMGZauQzJ)

### URLルーティングの設定

Layoutテンプレートの指定やURLへのテンプレートのマッピングは`Router`オブジェクトの属性を設定することで行います。そこで下記のコードを記述した`route.js`を`client/lib`以下に作成します。ここでは以下の動作を記述しています。

* Layoutテンプレートとして`walletLayout`を指定。
* URLが'/'の場合は'/dashboard'にリダイレクトさせる。（例えば、<http://localhost:3000> のリクエストが来た場合、<http://localhost:3000/dashboard> にリダイレクトさせる。）
* URLが'/dashboard'の場合はRouteテンプレートとして`dashboard`テンプレートを割り当てる。
* URLが'/send'の場合はRouteテンプレートとして`send`テンプレートを割り当てる。

> client/lib/route.js

```javascript
Router.configure({
  //Layoutテンプレートの指定
  layoutTemplate: 'walletLayout'
});

Router.route('/', function () {
  //リダイレクト設定
  this.redirect('/dashboard');
});

//URLとRouteテンプレートのマッピングを指定
Router.route('/dashboard', {name: 'dashboard'});
Router.route('/send', {name: 'send'});
```

### Layoutテンプレートの追加

Layoutテンプレートとして指定した`walletLayout`テンプレートとそのヘルパー関数を追加します。iron:routerはLayoutテンプレートを自動的にhtmlファイルの`<body>`タグ内に展開するように動作するため、この`walletLayout`テンプレートでは`<body>`タグの内部に記述されるべきコードのみを記述します。また元々`<body>`タグとその内部を記述していた`main.html`からは当該箇所を削除します。

> client/templates/wallet\_layout.html

```markup
<template name="walletLayout">
  <nav class="navbar navbar-default">
    <div class="container-fluid">
      <div class="navbar-header">
        <a class="navbar-brand" href="{{pathFor 'dashboard'}}">Simple Ether Wallet</a>
      </div>
      <ul class="nav navbar-nav">
        <li class="{{activeIfCurrent 'dashboard'}}"><a href="{{pathFor 'dashboard'}}">Dashboard</a></li>
        <li class="{{activeIfCurrent 'send'}}"><a href="{{pathFor 'send'}}">Send Ether</a></li>
      </ul>
    </div>
  </nav>
  <main class="container-fluid">
    {{> yield}}
  </main>
</template>
```

> client/templates/wallet\_layout.js

```javascript
Template.walletLayout.helpers({
  //ナビゲーションバーのアイテムをハイライトするためのヘルパー関数
  activeIfCurrent: function (template) {
    var currentRoute = Router.current();
    if(currentRoute && template === Router.current().route.getName()){
      return 'active';
    }else{
      return '';
    }
  }
});
```

> client/main.html

```markup
<head>
  <title>Simple Ether Wallet</title>
</head>
```

以上までの手順で、ナビゲーションバーとURLとテンプレートのマッピング機能が追加されました。次にURLにマッピングされた各ビューのテンプレートを追加していきます。

## DashboardとSendビューの追加

### Dashboardビュー

Dashboardビュー用のテンプレートを追加していきます。Dashboardビューでは「簡単なEtherのWalletを作る（１）」の節で追加していったものと同じ

* Account Balance
* Node Status
* Block Status

の３つのコンポーネントで構成することにします。そのためDashbordビューのテンプレートとしてこれらのコンポーネントのテンプレートを呼び出すように下記のコードを追加することで、Dashboardビューの表示が可能になります。

> client/templates/views/dashboard.html

```markup
<template name="dashboard">
  <div class="row-fluid">
    <div class="col-md-8 col-md-offset-2">
      {{> accountBalanceComponent}}
      {{> nodeStatusComponent}}
      {{> blockStatusComponent}}
    </div>
  </div>
</template>
```

dashboardビューはこれで完成です。

### Sendビュー

次に、Sendビューのテンプレートとして下記のコードを追加します。以降の節でSendビューの機能を追加していきますが、ここではその土台として下記のように「Account Balance」のコンポーネントのみ追加しています。

> client/templates/views/send.html

```markup
<template name="send">
  <div class="row-fluid">
    <div class="col-md-8 col-md-offset-2">
      {{> accountBalanceComponent}}
    </div>
  </div>
</template>
```

以上までで、以下のイメージのようにナビゲーションバーからそれぞれのビューに遷移が可能になります。

![](/files/-M41_ICkKARoDoars-G6)

【Dashboardビューでの表示】

![](/files/-M41_JJjeUqdO-YdeOS6)

【Sendビューでの表示】

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step006")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step006)

## 送金機能の追加

Sendビューに「Send Ether」コンポーネントを追加しEtherを送金する機能を実装していきます。下図のように送金元アドレスと送金先アドレス、および送金するEtherの額を入力し「Submit」ボタンを押下することで送金を確認するモーダルウィンドウが表示され、そこで「Yes」を押下するとEthereumのノードにトランザクションが送信される動きをします。

![](/files/-M41_JJlwskL2MnQn8sf)

【Submitボタンを押下するとモーダルの確認画面が表示される】

### 送金情報入力画面と確認画面の表示

まずは送金情報を入力する画面と送金の確認を行う画面までを作成していきます。また送金の確認画面では送金に必要なFeeの表示も行います。

Sendビューのテンプレートに既存の`accountBalanceComponent`のInclusionsタグの後に`sendEtherComponent`のInclusionsタグを追加します。

> client/templates/views/send.html

```markup
（前略）
      {{> accountBalanceComponent}}
      {{> sendEtherComponent}}
（後略）
```

そして追加した`sendEtherComponent`テンプレートのコードを下記のように追加します。

> client/templates/components/send\_ether\_component.html

```markup
<template name="sendEtherComponent">
  <div class="panel panel-primary">
    <div class="panel-heading">
      <h4>Send Ether</h4>
    </div>
    <div class="panel-body">
      <form class="form-horizontal">
        {{> sendInputTemplate inputId="f-addr" labelStr="From:" placeholderStr="0x1234abcdef...."}}
        {{> sendInputTemplate inputId="t-addr" labelStr="To:" placeholderStr="0x1234abcdef...."}}
        {{> sendInputTemplate inputId="amount" labelStr="Amount(ETH):" placeholderStr="0.0"}}
        <input type="submit" value="submit" class="btn btn-primary col-md-offset-6"/>
      </form>
    </div>
  </div>
  {{> sendConfirmModalTemplate}}
</template>

<template name="sendInputTemplate">
  <div class="form-group">
    <label class="control-label col-md-3" for="{{inputId}}">{{labelStr}}</label>
    <div class="controls col-md-6">
      <input name="{{inputId}}" id="{{iputId}}" type="text" value="" placeholder="{{placeholderStr}}" class="form-control"/>
    </div>
  </div>
</template>

<template name="sendConfirmModalTemplate">
  <div class="modal fade" id="sendConfirmModal">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header alert-danger">
          <h4 class="modal-title">Confirmation</h4>
        </div>
        <div class="modal-body">
          <h4>Send {{sendAmountInEther}} ETHER</h4>
          <ul>
            <li><b>From:</b> {{fAddr}}</li>
            <li><b>To:</b> {{tAddr}}</li>
            <li><b>Estimated Fee:</b> {{fee}} ETHER</li>
          </ul>
          <br/>
          <h4>Do you really send the Ether?</h4>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" id="send">Yes</button>
            <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        </div>
      </div>
    </div>
  </div>
</template>
```

送金情報をSession変数で管理するために、初期化のコードを`initSessionVars`関数内に追記します。

> client/lib/modules/init\_session\_vars.js

```javascript
//Session変数の初期化
initSessionVars = function(){
(中略）
//送金関連の変数
var initialFundInfo = {
  amount:0,
  fAddr:0x0,
  tAddr:0x0,
};
Session.setDefault("sendEther.fundInfo", initialFundInfo);
Session.setDefault("sendEther.estimatedGas", 0);
Session.setDefault("sendEther.currentGasPrice", 0);

};
```

送金入力画面及び確認画面のヘルパと送金入力画面のイベント処理のコードを追加します。

> client/templates/components/send\_ether\_component.js

```javascript
//送金に必要なFeeの計算。
//必要なFee ＝ 必要Gas × Gasプライス
var estimatedFeeInWei =  function(){
  var gas = Session.get('sendEther.estimatedGas');
  var gasPrice = new BigNumber(Session.get('sendEther.currentGasPrice'));
  return gasPrice.mul(gas);
}

var estimationCallback = function(e, res){
    var template = this;
    console.log('Estimated gas: ', res, e);
    if(!e && res) {
        Session.set('sendEther.estimatedGas', res);
    }
};

var getGasPriceCallback = function(e, res){
    var template = this;
    console.log('Current Gas Price in Wei: ', res.toString(10), e);
    if(!e && res) {
        Session.set('sendEther.currentGasPrice', res.toString(10));
    }
};

Template.sendEtherComponent.events({
  //「Send Ether」コンポーネントのSubmitボタン押下時のイベント制御
  'submit form': function(e) {
    var template = this;
    e.preventDefault(); //ボタン押下時のブラウザでのデフォルト動作の禁止

    //画面で入力された送金情報を「fundInfo」オブジェクトに格納
    var fundInfo = {
      fAddr: $(e.target).find('[name=f-addr]').val(),
      tAddr: $(e.target).find('[name=t-addr]').val(),
      amount: web3.toWei($(e.target).find('[name=amount]').val(),'ether')
    };

    if(EthAccounts.findOne({address: fundInfo.fAddr}, {reactive: false})) {
      //送金情報をSession変数に格納
      Session.set('sendEther.fundInfo', fundInfo);

      //必要Gas量の見積もりをEthereumノードに問い合わせ→ Session変数に格納
      web3.eth.estimateGas({from: fundInfo.fAddr, to: fundInfo.tAddr, value: fundInfo.amount}, estimationCallback.bind(template));

      //現在のGas priceをEthereumノードに問い合わせ問い合わせ→ Session変数に格納
      web3.eth.getGasPrice(getGasPriceCallback.bind(template));

      //送金確認画面（モーダルウィンドウ）の表示
      $('#sendConfirmModal').modal('show');
    }
  }
});

//送金確認画面のヘルパー
Template.sendConfirmModalTemplate.helpers({
  sendAmountInEther: function(){
    var amountEth = web3.fromWei(Session.get("sendEther.fundInfo").amount,'ether');
    return parseFloat(amountEth).toFixed(3);
  },
  fAddr: function(){
    return Session.get("sendEther.fundInfo").fAddr;
  },
  tAddr: function(){
    return Session.get("sendEther.fundInfo").tAddr;
  },
  fee: function(){
    return web3.fromWei(estimatedFeeInWei(),'ether').toString(10);
  }
});
```

## トランザクションの送信

ここまでで、

* 送金情報の入力
* 必要なFeeの計算
* 確認画面の表示

といったEtherの送金の準備に必要な機能が追加されました。次に確認画面で「Yes」ボタンを押下することで、入力内容のトランザクションをEthereumネットワーク上に送信する機能を追加します。

トランザクションの送信は送金確認画面のテンプレートにイベントリスナーを追加することで実現します。以下のコードを`send_ether_component.js`の末尾に追加します。送金画面で「Yes」をクリックした際に、トランザクション送信のための非同期関数[`web3.eth.sendTransaction`](https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethsendtransaction)を呼び出す処理を行っています。またそのコールバック関数内でエラーが無ければトランザクションの送信が成功した旨、エラーがあれば失敗した旨をダイアログボックスに表示することを行っています。

> client/templates/components/send\_ether\_component.js

```javascript
（前略）
//送金確認画面のイベントリスナー
Template.sendConfirmModalTemplate.events({
  //送金確認画面で「Yes」をクリックした場合のイベントハンドラー
  'click #send': function(e) {
    e.preventDefault();
    var fundInfo = Session.get("sendEther.fundInfo");
    //非同期関数「web3.eth.sendTransaction」を呼ぶことでノードにトランザクションを送信
    web3.eth.sendTransaction({
      from: fundInfo.fAddr,
      to: fundInfo.tAddr,
      value: fundInfo.amount
    }, function(error, txHash){ //戻り値としてトランザクションハッシュ値が返る
      console.log("Transaction Hash:", txHash, error);
      if(!error) {
        alert("Ether Transfer Succeeded");
      } else {
        alert("Ether Transfer Failed");
      }
    });
    $('#sendConfirmModal').modal('hide');
}});
```

これで、Etherの送金が可能になりました。実際に今回追加した機能で送金を行ってみましょう。送金を行い暫くすると送金に基づいてアカウントのEtherの残高が変化するはずです。

ここでアカウントの残高は送金（トランザクション送信）と同時に変化するのではなく採掘者がそのトランザクションをブロックに入れ採掘したタイミングで変化することに注意してください。

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step007")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step007)


# 簡単なEtherのwalletを作る（３）

前節では「simple-ether-wallet」に送金を行う機能を追加しました。walletの画面上で送金を行うとネットワーク上に送金のトランザクションが送信され、それを採掘者が採掘することでアカウントの残高が変化しました。

ブロックチェーンを用いた送金では、あるトランザクションが組み込まれたブロックが採掘されることでそのトランザクションが「1回の承認（confirmation）を得た」と考えます。そしてそのブロックの後ろに続くブロックが採掘されればその数に応じて承認の数が増えて、そのトランザクションの信頼が高まります。Ethereumではおおよそ12回の承認を得ることでほぼ間違いなく信頼ができると言われています。

この節では下図の赤枠のようにwalletが送信したトランザクションの履歴とそれらのトランザクションが何回承認（confirmation）されたかを表示する機能を追加します。

![](/files/-M41_Hm979hDK22ruJdu)

※前節に続きここで説明するアプリケーションのソースコードは[GitHub上](https://github.com/a-mitani/simple-ether-wallet)に公開しています。

## Transactionsコレクションを定義

トランザクションの履歴を保管し管理するためにMeteorのCollectionオブジェクトを利用します。MeteorのCollectionオブジェクトはサーバサイドやブラウザのローカルストレージ上にデータを格納し永続的にデータを保持することも可能ですが、ここでは簡単のためにブラウザ上のメモリ上のみに履歴を保存することにします。（そのため、ブラウザのタブを閉じれば履歴はクリアされます。）トランザクション履歴のCollectionオブジェクトとして`Transactions`を定義するコードを`client/lib/init.js`内に追加します。

> client/lib/init.js

```javascript
（前略）
//Session変数の初期化
initSessionVars();

//Transactionsコレクションの初期化
Transactions = new Mongo.Collection('transactions', {connection: null});

//オブザーバの起動
observeNode();
```

アプリが正しく動作していれば、このコードを追加したあと、ブラウザコンソール上で下記のようにコレクション内の全てのドキュメント（レコード）を取り出すコマンド`Transactions.find().fetch();`を実行してみると`[]`のように空の配列が返されるはずです。（Transactionsオブジェクトは定義したものの、まだデータは何も入れていないため空の配列が返されます。）

> ブラウザコンソール上

```
> Transactions.find().fetch();
  []
```

## トランザクション情報を登録

Transactionsコレクションが定義されたので、Etherの送金を実行した際にそのトランザクション情報をTransactionsコレクションに登録するようにします。

トランザクションの送信を行う`web3.eth.sendTransaction`関数のコールバック関数内で`alert("Ether Transfer Succeeded");`としていた部分の代わりに次のようなTransactionsコレクションへのドキュメント追加を行う処理を追加し下記のようにします。

> client/templates/components/send\_ether\_component.js

```javascript
（中略）
    //非同期関数「web3.eth.sendTransaction」を呼ぶことでノードにトランザクションを送信
    web3.eth.sendTransaction({
      from: fundInfo.fAddr,
      to: fundInfo.tAddr,
      value: fundInfo.amount
    }, function(error, txHash){ //戻り値としてトランザクションハッシュ値が返る
      console.log("Transaction Hash:", txHash, error);
      if(!error) {
        //発行したトランザクション情報をTransactionsコレクションに挿入
        Transactions.upsert(txHash, {$set: {
          amount: Session.get("sendEther.fundInfo").amount,
          from: Session.get("sendEther.fundInfo").fAddr,
          to: Session.get("sendEther.fundInfo").tAddr,
          timestamp: getCurrentUnixTime(),
          transactionHash: txHash,
          fee: estimatedFeeInWei().toString(10),
        }});
      } else {
        alert("Ether Transfer Failed");
      }
    });
    $('#sendConfirmModal').modal('hide');
}});
```

また、上記で追加した部分に現在のUNIX時刻を求める新しい関数を利用しているのでその定義を下記のように追記します。

> client/lib/modules/time\_utils.js

```javascript
（前略：既存コード）
//現在のUNIX時刻を取得（単位：秒）
getCurrentUnixTime = function(){
  var date = new Date() ;
  var unixTimeSecond = Math.floor( date.getTime() / 1000 ) ;
  return unixTimeSecond;
};
```

以上の修正を行った上で、アプリ上で送金の操作を行い、ブラウザコンソール上で再度、`Transactions.find().fetch();`コマンドを実行してみてください。送金を行った情報がドキュメントとして保存されたのが見て取れるはずです。

## トランザクション情報を表示

次にTransactionsコレクションの情報を画面上に表示する機能をつけ加えていきます。Sendビューに`latestTransactionComponent`テンプレートを付け加え、このテンプレート内でTransactionsコレクションを表示する機能を実装していきます。

まずは、下記のようにSendビューのテンプレートにInclusionsタグ`{{> latestTransactionComponent}}`を追加します。

> client/templates/views/send.html

```markup
<template name="send">
  <div class="row-fluid">
    <div class="col-md-8 col-md-offset-2">
      {{> accountStatusComponent}}
      {{> sendEtherComponent}}
      {{> latestTransactionComponent}}
    </div>
  </div>
</template>
```

新しく、`client/templates/components/`以下に`latest_transaction_component.html`と`latest_transaction_component.js`のテンプレートとそのヘルパのファイルを下記のように追加します。ここでTransactionsコレクションに何も登録されていない場合は「No Transactions To Show」と表示し、一つ以上トランザクションが登録されていればTransactionsコレクションから`find`メソッドを用いて

* トランザクションの発生日時
* 送金元アドレス
* 送金先アドレス
* 送金額

  を取り出し表示することを行っています。また現時点では承認回数をゼロで固定に表示しています。（後程、リアルタイムに承認回数を表示する機能を実装していきます。）

> client/templates/components/latest\_transaction\_component.html

```markup
<template name="latestTransactionComponent">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4>Latest Transactions (Limit 5)</h4>
    </div>
    <table class="table table-striped" >
      <tbody>
        {{#each items}}
          {{> transactionItem}}
        {{else}}
          <tr>
           <td> No Transactions To Show</td>
          </tr>
        {{/each}}
      </tbody>
    </table>
  </div>
</template>

<template name="transactionItem">
  <tr>
    <td>
      <ul>
        <li><b>Datetime:</b> {{txDateTime}} </li>
        <li><b>From:</b> {{from}}</li>
        <li><b>To:</b> {{to}}</li>
      </ul>
    </td>
    <td>
      <h4>
        <b>{{amountInEther}}</b> ETHER
      </h4>
      <b>{{confirmationCount}}</b> confirmations
    </td>
  </tr>
</template>
```

> client/templates/components/latest\_transaction\_component.js

```javascript
//latestTransactionComponentテンプレートのヘルパー
Template.latestTransactionComponent.helpers({

  //Transactionsコレクションから最大5件のトランザクション情報を取得
  //timestamp属性について降順で取り出す。
  items: function(){
    selector = {};
    return Transactions.find(selector, {sort: {timestamp: -1}, limit: 5}).fetch();
  }
});


//transactionItemテンプレートのヘルパー
Template.transactionItem.helpers({

  //フォーマット化されたトランザクション時刻の取得
  txDateTime: function(){
    return unix2datetime(this.timestamp);
  },

  //送金額をEtherの単位で取得
  amountInEther: function(){
    var amountEth = web3.fromWei(this.amount, "ether");
    return parseFloat(amountEth).toFixed(3);
  },

  //承認回数の取得（現時点では固定でゼロを返す関数）
  confirmationCount: function(){
    var count = 0;
    return count;
  }
});
```

以上のコードを追加した後、画面から送金操作を行うとSendビューの下部に実際に送金した情報がリスト上に表示されるでしょう。

![](/files/-M41_HmCUvskgA8F7Blx)

&#x20;[**View this Commit On GitHub (Tag:"Step008")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step008)

## 承認状態の監視と表示

最後に、ウォレットで送金したトランザクションの承認状態を監視しそれを表示する機能を付け加えてきましょう。この機能は大まかに以下の方法で実現していきます。

* Transactionsコレクションの登録状況を常時ウォッチする機能を追加
  * コレクションにトランザクションが新しく追加されたら、そのトランザクションの承認状態の監視を開始。
  * コレクションからトランザクションが削除されたら、そのトランザクションの承認状態の監視を停止。
* Ehtereumネットワーク上で新しいブロックが採掘されるたびに監視対象のトランザクションの承認状態をチェックする。承認状態の監視は、当該トランザクションが採掘されたブロックの後ろに12個のブロックが追加されるまで行い、その後は監視を停止する。

まずはwalletアプリ起動時にTransactionsコレクションの登録状況の監視を開始するためのメソッドを呼び出すように、`client/lib/init.js`の末尾に下記のコードを追加します。

> client/lib/init.js

```javascript
（前略）
observeTransactions();
```

また、上記で追加した`observeTransactions()`メソッドを下記のように実装します。

> client/lib/modules/observe\_transactions.js

```javascript
//Transactionsコレクションの状態を監視
observeTransactions = function(){
    Transactions.find({}).observe({
        //Transactionsコレクションにドキュメントが追加された場合
        added: function(newDocument) {
          console.log("Added Transaction Document");
          checkTransactionConfirmations(newDocument);
        },
        //Transactionsコレクションからドキュメントが削除された場合
        removed: function(document) {
          console.log("Removed Transaction Document", document._id);
        }
    });
};
```

次に、上記コード内で呼ばれているcheckTransactionConfirmations()メソッドを実装します。処理の内容はソースコード内のコメントを参照してください。

> client/lib/modules/check\_transaction\_confs.js

```javascript
//承認状態監視停止の閾値
var requiredConfirmations = 12;

//web3.eth.getTransactionと、web3.eth.getTransactionReceipt のAPIメソッドで得られた情報をもとに
//Transactionsコレクションをアップデート
var updateTransaction = function(oldDocument, transaction, receipt){
  if(receipt && transaction){
    var actualFee = transaction.gasPrice.times(new BigNumber(receipt.gasUsed)).toString(10);
      Transactions.update({_id: oldDocument._id},
                          {$set: {
                                  blockNumber:transaction.blockNumber,
                                  blockHash: transaction.blockHash,
                                  transactionIndex: transaction.transactionIndex,
                                  fee: actualFee
                                 }
                          });
  }else{
    console.log("NOT UPDATED");
  }
};


//最新ブロックを監視し、トランザクション（tx）の承認状態をアップデートする。
checkTransactionConfirmations = function(tx){
  var confCount = 0;
  var filter = web3.eth.filter('latest');

  //最新ブロックを監視。新しいブロックが採掘されれば、コールバック関数内で指定された処理を行う。
  filter.watch(function(e, blockHash){
    if(!e) {
      console.log("Received New Block");
      confCount++;

      // Transactionsコレクションから最新状態を取得。
      // Transactionsコレクションから削除されていれば監視を停止
      tx = Transactions.findOne(tx._id);
      if(!tx) {
        filter.stopWatching();
        return;
      }

      //web3.eth.getTransactionとweb3.eth.getTransactionReceiptの２つのAPI関数の返り値をもとに、
      //最新のトランザクションの状態を取得。
      web3.eth.getTransaction(tx.transactionHash, function(e, transaction){
        web3.eth.getTransactionReceipt(tx.transactionHash, function(e, receipt){
          if(!e) {

            //発信したトランザクションを含むブロックが相当の期間採掘されない場合は、
            //当該トランザクションがEthereumネットワークに受け入れられなかったとして、
            //Walletのトランザクションの歴から削除する。
            //ここで「相当の期間」として、requiredConfirmationsに指定された値の２倍としている。
            if(!receipt || !transaction){
              if(confCount > requiredConfirmations*2){
                Transactions.remove(tx._id);
                filter.stopWatching();
                return;
              }else{
                return;
              }

            // 発信したトランザクションを含むブロックが採掘された場合、
            // その情報でTransactionsコレクションの情報を更新。
            }else if(transaction.blockNumber) {
              if(transaction.blockNumber !== tx.blockNumber){
                updateTransaction(tx, transaction, receipt);
              }
              // Transactionsコレクションでのブロックハッシュと、
              // 最新のEthereumネットワーク上でのブロックハッシュが異なる場合、
              // 当該トランザクションを含むブロックは正規のブロックチェーン内に無いことを示すため、
              // Walletのトランザクション履歴から削除する。
              web3.eth.getBlock(transaction.blockNumber, function(e, block) {
              if(!e) {
                if(block.hash !== transaction.blockHash) {
                  // remove if the parent block is not in the chain anymore.
                  Transactions.remove(tx._id);
                  filter.stopWatching();
                  return;
                }
              }
              });

              // 承認回数が指定回数以上になった場合、十分信頼性が高いとして、
              // 当該トランザクションの承認状態の監視を停止する。
              var confirmations = (EthBlocks.latest.number + 1) - tx.blockNumber;
              if(confirmations > requiredConfirmations){
                console.log("Confirmed Enough. Stop Watching... TxHash=", tx.transactionHash);
                filter.stopWatching();
              }
            }
          }
        });
      });
    }
  });
};
```

また、最後に承認回数を画面に表示するために、`transactionItem`テンプレートヘルパの承認回数の取得部分をTransactionsコレクションと最新のブロックナンバーの差から表示するように、以下のように修正します。

> client/templates/components/latest\_transaction\_component.js

```javascript
（前略）
  //承認回数の取得
  confirmationCount: function(){
    var count = 0;
    if(this.blockNumber) count = EthBlocks.latest.number - this.blockNumber +1;
    if(count > 50) count = "50+";
    return count;
  }
（後略）
```

![](/files/-M41_HmEW_GCkY99dm2S)

&#x20;[**View this Commit On GitHub (Tag:"Step009")**](https://github.com/a-mitani/simple-ether-wallet/releases/tag/step009)


# 独自通貨を作る


# コントラクト指向言語Solidity詳解

前章までで述べてきたとおり、分散アプリケーションやスマート・コントラクトは、ブロックチェーン上に記録される、コントラクト・コードが実行されることによって動作します。 Ethereumネットワーク上では、このコントラクト・コードは「Ethereum Virtual Machine Code」または略して「EVM Code」と呼ばれる、バイトコードの形式で記述され処理されます。 このようなバイトコードの形式は低水準の機械言語であって、人間にとっては可読性が悪く開発の生産性も悪いものとなっています。そこでEthereumでは、可読性と生産性が高く、コントラクトを記述することに特化した高水準言語と、それを EVM Code に翻訳するためのコンパイラが幾つか開発されています。その代表的なものとして「Solidity」が挙げられます。 ここでは、このプログラミング言語「Solidity」について解説していきます。


# 基本的な記法

## Hello world

下記にSolidityで記述された最も単純なスマート・コントラクトのコードの例（HelloWorld)を示します。

```
// Simple contract that returns constant string "Hello World"
contract HelloWorld {
    function get() constant returns (string retVal) {
        return "Hello World!!";
   }
}
```

このContractは、`get()`関数が呼び出されたら固定の"Hello World!!"という固定の文字列を返すというものです。

## Contract

上記のようにSolidityにおいて`contract`句で宣言されるContractが基本の構成要素であり、スマート・コントラクトは、この`contract`句に処理を記述していくことで実装されます。

Solidityでは次の構文でContractを定義します。

```
contract Contract名 {
   //スマート・コントラクトで行う処理をここに記述
}
```

ここで「・・・・」の部分にContractの具体的な内容が記述されます。ContractはJavaやPythonなどオブジェクト指向言語での「クラス」に似たものであり、クラス変数に相当するような内部状態を保持するストレージ部分やメソッドに相当するような関数、その中で有効なローカル変数などを持ちます。

HelloWorldの例では`get()`関数が定義され、その中では文字列`Hello World`を返す処理が定義されていました。

なお、1つのソースファイル上に複数のContractを定義することも可能です。

## 小文字・大文字の区別

Solidityでは、Contract名や関数名、変数名などは大文字と小文字が区別されます。例えば上述のContractのHelloWorldは「helloworld」の名前で呼ぶことはできません。「HelloWorld」と「helloworld」は別のものと解釈されます。

## 文（Statement）最後にはセミコロンをつける

Solidityで記述されたコードは一般的に１つ以上の文（Statement）から構成されます。例えば上記のコードの例では、`return "Hello World!!";`は1つの文であり、最後にセミコロンが付加されています。

## コメント

Solidityでは他のプログラミング言語と同様Solidityでも「コメント」を付加することが可能です。コメントを記述するには以下の２つの方法があります。

### 「//」でのコメント

単一行のコメントを記述する際に用います。「//」を付加することで、その後の部分がコメントとみなされます。

### 「/\* ～ \*/」でのコメント

複数でまたがるコメントを記述する際に用います。 「/\*」と「\*/」で囲まれたブロックがコメントとみなされます。


# 変数とデータ型

## 変数の宣言

Solidityは静的型付け言語であり、変数を定義する際にそこに格納するデータ型を明示する必要があります。 以下に符号付整数である`int`型の変数`x`を宣言する例を示します。

```
int x;
```

また次のように宣言時に初期値を指定する事も可能です。

```
int x = 10;
```

ちなみに初期値を設定しない場合には、各型のデフォルト値が格納されます。例えば`int`の場合、`0`が格納されます。 &#x20;

## データ型

#### 基本型と参照型

先に記したとおり、Solidityは静的型付け言語であり、変数を扱う際にはその変数のデータ型を強く意識する必要があります。Solidityには様々なデータ型が規定されていますが、それらは大きく基本型 と参照型という２つのタイプに分類されます。

これらは変数に格納される際の方法に違いがあります。まず基本型の変数には、「値そのもの」が格納されます。一方で参照型の変数には「値を格納しているメモリ上のアドレス（参照）」が格納されます。この動作の違いにより基本型と参照型で変数を扱う際の挙動に違いが生まれます。基本形であるuint型の変数と、参照型である配列の変数を例にして、両者で代入の挙動の挙動に違いをみてみましょう。

```
contract VarTypeTest {
  function valType() constant returns (uint retVal){ 
    uint a; 
    a = 10; 
    uint b = a; // (1)
    b = 20;  // (2)
    return a; // Execution result shows 10 !
  }

  function refType() constant returns (uint[2] retVal){
    uint[2] x;
    x[0] = 100;
    x[1] = 200;
    uint[2] y = x; //(3)
    y[0] = 500; // (4)
    y[1] = 600; // (4)
    return x; // Execution result shows [500, 600] !
  }
}
```

関数`valType()`では基本型であるuintの変数を代入した場合の挙動を試験しています。(1)の行では、変数`a`に代入された「10」という値そのものがコピーされて変数`b`に代入されます（**値渡し**）。その結果`b`の値が(2)で変更されても、元の変数`a`の内容には影響を与えません。その結果この関数の実行結果は`10`が示されます。

一方で関数`refType()`では参照型である配列の変数を代入した場合の挙動を試験しています。配列の変数は参照型であり、参照型の変数には「値を格納しているメモリ上のアドレス（参照）」が格納されています。そのため(3)で配列`x`を`y`に代入していますが、ここで実際に行われていることは、変数`x`の値を格納しているメモリ上のアドレスを変数`y`にセットしていることになります（**参照渡し**）。そのためこの時点で`x`と`y`は同じ場所を見ていることになり、(4)で`y`の内容を変えると同時に変数`x`の内容も変更されることになります。結果、この関数の実行結果は`[500, 600]`が示されます。

以下の表はSolidityで規定されている主なデータ型の分類です。 ![データ型分類](/files/-M41_ILo2jlukFnQe4YO)

以下でSolidityで規定されている基本型と参照型のそれぞれのデータ型について見ていきます。

### 符号付き整数型

以下の例のように符号付き整数型は`int●`句を用いて宣言します。ここで「●」は変数のビット長の指定であり8\~256までの8の倍数が指定されます。例えばint8は8ビット符号付整数型を表わします（-128 ～ 127）。数字が省略され`int`と指定された場合は`int256`を意味します。またデフォルト値は0です。

```
int16 a = -10;  // 16 bitの符号付き整数型を宣言し「-10」を格納。
int b = 100;    // 256 bitの符号付整数型を宣言し「100」を格納。
int c;  //代入を行わないとデフォルト値「0」が格納される。
```

### 符号なし整数型

以下の例のように符号なし整数型は`uint●`句を用いて宣言します。ここで「●」は変数のビット長の指定であり8\~256までの8の倍数が指定されます。例えばuint8は8ビット符号なし整数型を表わします（0 ～ 255）。数字が省略され`uint`と指定された場合はuint256を意味します。またデフォルト値は0です。

```
uint16 a = 10;  // 16 bitの符号付き整数型を宣言し「10」を格納。
uint b = 100;    // 256 bitの符号付整数型を宣言し「100」を格納。
uint c;  //代入を行わないとデフォルト値「0」が格納される。
uint d = -10; //【コンパイルエラー】uint型に負値は格納不可。
```

### 真偽型

真偽（論理）型変数は`bool`句により宣言します。`true`（真）または`false`（偽）の２値のみが格納可能です。デフォルト値は`false`になります。&#x20;

### アドレス型

アドレス型はEOAやContractの20バイトの長さのアドレスを格納する型であり`address`句で宣言します。

```
address a = 0xabc;  // "0x0000000000000000000000000000000000000abc"のアドレス値が格納される。
address b; //デフォルト値は"0x0000000000000000000000000000000000000000"
```

#### ■ balance属性

アドレス型には`balance`属性が規定されています。例えば下記の例の用にbalance属性を用いると指定のアドレスが保有するetherの量が取得可能です。

```
address a = 0xa; //アドレス型変数aに0xaのアドレスを格納。
uint b = a.balance; //アドレス"0xa"の持つetherの量をbに格納。
```

#### ■ send()関数

アドレス型には`send`関数が規定されています。`<address>.send(x);`により指定のアドレス`<address>`に`x`weiのetherを送金することができます。以下に実際に送金を行う簡単なコントラクトのコードを示します。

```
contract Test {
    function sendTest(){
        address a = 0xf2057b8aefb9093331faf48f30c1ebeab4ff961d; //送信先のアドレスの指定
        a.send(5); //コントラクト・アドレスが保有するetherから指定のアドレス"a"へ5wei送金
    }
}
```

【TIP】実際に上記のコントラクトのsendTest関数を動かす際は、コードをコンパイルしブロックチェーンに登録後、本コントラクトのアドレスに5wei以上のetherを送金しておく必要があります。というのもsendTest()関数はコントラクトが保有するetherを指定のアドレスに送る関数であるためです。また、アカウントの状態を変える関数のために、「Contractを作成してみる」節で説明したとおり、sendTestの関数の実行はsendTransaction関数を用いて呼び出す必要があります。&#x20;

### 配列

Solidityでは、固定長、可変長のどちらの配列型も扱うことが可能です。配列要素の型はストレージ変数の場合は任意のデータ型の配列を定義することが可能です。&#x20;

固定長配列は、データ型`T`、長さ`k`の配列は`T[k]`で宣言します。一方可変長配列の場合は`T[]`とします。

以下に、固定長配列を扱うSolidityコードの例を示します。

```
contract arrayTest {
    uint8[5] uintArray;
    string[3] stArray;

    function arrayTest(){ // コンストラクタ
        uint8 x = 0;
        while(x < 5){
            uintArray[x] = 100 - x;
            x++;
        }

        stArray[0] = "Apple";
        stArray[1] = "Orange";
        stArray[2] = "Pineapple";
    }

    //uint型配列全体を取り出す。
    function getUintArray() constant returns (uint8[5]){
        return uintArray;
    }

    //uint型配列の特定の要素（x番目の要素）を取り出す。
    function getUintValue(uint8 x) constant returns (uint8){
        return uintArray[x];
    }

    //string型配列の特定の要素（x番目の要素）を取り出す。
    function getStValue(uint8 x) constant returns (string){
        return stArray[x];
    }
/*
    //string型配列全体を取り出す。（Not Supported）
    function getStArray() constant returns (string[3]){
        return stArray;
    }
*/
}
```

上記のContractコードをコンパイルし、ブロックチェーン上に登録しContractのそれぞれの関数を呼び出すと下記のような実行結果になります。

```
> arraytest.getUintArray()
[100, 99, 98, 97, 96]
> arraytest.getUintValue(2)
98
> arraytest.getStValue(1)
"Orange"
```

また、上記Contractコードでコメントアウトしている関数（getStArray）はstring型の配列全体を返す関数を意図していますが現バージョンのコンパイラでは「Error: Internal type is not allowed for public and external functions.」というエラーになりコンパイルできません。これはuint等とは異なり、文字列型自体がコンパイラ内でバイト配列型として扱われており、「文字列型の配列」はネストされた２次元配列として扱われます。現バージョンコンパイラは、ネストされた配列を関数の引数または返り値に指定することをサポートしておらず、エラーになります。

#### ■ length属性、push関数

配列には配列長さを示す`length`属性が規定されています。可変長配列では下記の例のようにlength属性を指定することで配列要素を削除することも可能です。

また可変長配列の最後に要素を追加するpush関数が用意されています。使い方の例を以下に示します。

```
contract pushLengthTest {
    uint8 arraylength = 5;
    uint[] uintArray;

    function pushLengthTest(){ 
        uint8 i = 0;
        uint8 basenum = 10;
        while(i < arraylength){
            uintArray.push(basenum + i);
            i++;
        }
    }

    function getArray() constant returns (uint[]){
        return uintArray;
    }

    function getLength() constant returns (uint){
        return uintArray.length;
    }

    function setLength(uint x) returns (uint[]){
        uintArray.length = x;
        return uintArray;
    }
}
```

上記のContractコードをコンパイルし、ブロックチェーン上に登録しContractのそれぞれの関数を呼び出すと下記のような実行結果になります。

```
> pushlengthtest.getArray()
[10, 11, 12, 13, 14]
> pushlengthtest.getLength()
5
> pushlengthtest.setLength.sendTransaction(2, {from:eth.coinbase}) //Contractの状態変数を更新するためsendTransaction関数を使用する必要があることに注意。
"0x4a2b2cb6954b0cdd9dbae869f758d425334194736d0fb7f1c4913f4b75c17acb"
>
（トランザクションが採掘された後、再度getArray()関数を呼出す。）
> pushlengthtest.getArray()
[10, 11]  ← 先にlengthが2と指定されたため、indexが2以上の要素は削除される。
```


# 演算子


# 制御命令


# Ethereumの内部

追記予定


# さらに詳しく知るために


# Appendix

Ethereumを利用する際に便利な情報を、こちらに付録として追記していきます。


# Ethereum ウォレットの使い方（Metamask）

Ethereum（イーサリアム）を利用する最も簡易な方法はウォレット（wallet）を利用するものです。ウォレットは「財布」を意味し、仮想通貨であるEtherを保持・送金を可能にするものです。また幾つかのウォレットではスマート・コントラクトの実行も可能です。ウォレットは現在までに数多くリリースされており、以下に代表的なウォレットを示します。

* **MyEtherWallet（**[**公式サイト**](https://www.myetherwallet.com/)**）**：WebベースのEhtereumウォレットです。Webベースとはいえ、アドレスやその秘密鍵は外部サーバに保存されるわけではなく送金処理なども全てブラウザ上で動作します。秘密鍵等が外部に送信されることがないあめ、比較的安全に利用できます。多くの機能があり、Ethereum上のdAppのTokenの送受信も可能です。
* **MetaMask（**[**公式サイト**](https://metamask.io/)）：chrome拡張機能で利用できるウォレットです。このウォレットもアドレスやその秘密鍵は外部サーバに保存されるわけではなく送金処理なども全てブラウザ上で動作します。
* **Mist（**[**公式サイト**](https://ethereum.org/)）：Ethereumプロジェクトの公式ウォレットです。デスクトップクライアントとして動作します。
* **Trezor（**[**公式サイト**](https://trezor.io/)**）**：上記２つのウォレットは「ソフトウェア」ウォレットであるのに対して、このTrezorはハードウェア・ウォレットと呼ばれ筐体を持つデバイスの形をしたウォレットです。ウォレット内の仮想通貨を送金する際などに、PCに接続して利用しますが、それ以外の場合はPCから外しインターネットから完全に遮断された状態にすることが可能でありセキュリティが高いものになります。また、本ウォレットはEthreum以外の様々な種類の仮想通貨のウォレットとして利用が可能です。

  本節ではMetaMaskのイントールからEtherを送金する方法について記載します。

## MetaMaskのインストール

MetaMaskはChromeブラウザの拡張機能として動作するウォレットです。そのためChromeブラウザで、[公式サイト](https://metamask.io/)の「Get Chrome Extension」のリンクから下図のようなChromeウェブストアに移動します。次にウェブストアの右上にある「Chromeに追加」ボタンを押下すると、MetaMaskがchromeにインストールされ、URLバーの右に狐のマークが表示されます。これでインストールは完了です。

**【注意】**&#x43;hromeウェブストアには偽のMetaMaskのアプリ（フィッシングアプリ）も公開されている場合があるため、そのようなフィッシングのアプリでないことに十分気をつけてください。完全ではなく保証するものではないですがフィッシングに引っかからないためにここで書いたように公式サイト「 <https://metamask.io/> 」のURLのリンクをたどってChromeウェブストア画面に移動すること。またそのサイトのURLが下図のように 「nkbihfbeogaeaoehlefnkodbefgpgknn」 の文字列を含むことを確認することは最低限必要です。

![](/files/-M41_Hk3EFJcyWTILz1a)

## ウォレットの作成

URL横の狐マークを押下すると最初にいくつかのプライバシー関連の確認事項が表示され、それを承諾するとパスワードを入力する画面が表示されます。任意の8文字以上のパスワードを入力すると、下図のように「VAULT CREATED」と表示され、12個の英単語が表示されます。これがMetaMaskのウォレットのパスワードになるため、**絶対に他人から見れないように、また無くさないよう大切に保管してください**（図の単語はダミーです）。

![](/files/-M41_Hk5ct3lec_hAg-2)

ここで「I'VE COPIED...」のボタンを押下すると、ウォレットの作製が完了です。下図のような画面が表示されるはずです。

![](/files/-M41_Hk7KJERsVVAe-hw)

ここで、画面上部「Account 1」の下部に記された「0x5a60c...」が今回作製したウォレットに紐付くアカウントのアドレスであり、このアドレスに対してEtherが送金されることにより、ウォレットにEtherが貯まります。（後述しますが、一つのウォレットには複数のアカウント（アドレス）を紐づけることが可能です。）

## Etherを受送金する

### テストネットに接続

作製したウォレットでEtherを受け取ったり送金したりしていきます。Ethereumには本番のP2Pネットワークの他に、動作確認などをするためのテスト用のp2pネットワークがいくつか用意されています。本番のネットワーク上で本物のEther用意して受送金の動きを試すのは敷居が高いため、ここではテスト用のネットワークを利用して受送金の動作を確認していきます。 MetaMaskはデフォルトでは本番のネットワーク（Main Network）に接続されるため、まず、テスト用のネットワークに切り替えます。切り替えは、画面左上の「Main Network」と表示されている部分のプルダウンからテストネットワークを選択します。ここでは「Ropsten Test Network」を選択します（下図）。

![](/files/-M41_Hk92OWAQ94mJOsI)

### テスト用のEtherを受け取る

今回は、Rostpen Test Network上でテスト用のEtherを無料で発行してくれる「Rostpen Test Faucet」というサービスがあるので、それを利用することにします。

MetaMask上の「Buy」ボタンを押下すると「Rostpen Test Faucet」へのリンクが表示されるので、リンクを押下し「Rostpen Test Faucet」サイトへ移動します。そこで「Request 1 Ether」のボタンを押下すると「Test Faucet」のアドレスから、自分のアドレスに送金されます（下図）。

![](/files/-M41_HkBy1CAakjfd6ld)

１分程度待つと自身のウォレットの残高が0.0ethから1.0ethに更新されているはずです（下図）。

![](/files/-M41_HkDYsNnHLgSfILn)

### Etherを送金する

Faucetから受け取ったEtherを、別のアドレスに送金してみましょう。そのためにまず送信先のアドレスを作製しておきます。

MetaMaskのウォレットは複数のアドレスを作成し保持することができます。作製は非常に簡単で画面右上の人のマークを押下しプルダウンから「Create Account」を選択すると「Account 2」が作製されます。アカウントは再び画面右上の人のマークを押下しプルダウンからアカウントを洗濯することでアカウントの切り替えが可能です。

ここではMetaMask上で作製したAccount1 から Account2へ0.5Ether送金してみます。送金を行うためには送金元のアカウント（ここではAccount 1）の画面で「send」ボタンを押下します。すると送金に必要な情報を入力する画面に切り替わるので（下図）、「Recipient Address」には送金先（ここでは Account 2）のアドレスを入力し、「Amount」には0.5を入力します。

![](/files/-M41_HkFElJhCS2PSy-y)

「NEXT」ボタンを押下すると確認画面が表示されます（下図） ここで画面中央部で送金額と手数料の情報が記載されています。 Amountは送金額で今回は0.5ethとなっています。また、「Max Transaction Feeは」は送金に必要な最大の手数料を示しており、今回の送金では最大0.000021Eth手数料がかかるため、「Max Total」すなわち今回の送金によりAccount1のアドレスから差し引かれるEtherは0.500021ethとなる旨が記されています。

![](/files/-M41_HkHZzqKVQu2eMPl)

問題なければ「SUBMIT」ボタンを押下し送金を確定させます。 するとしばらくすると、ウォレット上のAccount2に0.5eth入金されます（下図）。また、Account1の残高は送金額に加え手数料も差し引かれ残高が0.499979ethとなります。

&#x20;![](/files/-M41_HkJk4yRtPWEy5J1) ![](/files/-M41_HkL6WancbFzfVZj)

送金の手数料や送金時の動作は[「Ethereumとは」節](/what_is_ethereum/ethereum_as_dapp_platform)に詳しく記しているためそちらを参照ください。

## 脚注


# （旧URL）

Ethereum入門は下記のURLに移動しました。

→ <http://book.ethereum-jp.net>


