12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MisocaAdvent Calendar 2017

Day 20

Ethereumのローカルネットワーク上で独自コインを送金する

Last updated at Posted at 2017-12-19

はじめに

こんにちは、Misocaの洋食(@yoshoku)です。

この記事は、Misoca Advent Calendar 2017の20日目の記事です。

ビットコインをはじめ暗号通貨(仮想通貨)がスゴイ人気ですね。メジャーな暗号通貨は、値段が高騰しすぎて手が出せそうにありませんが、暗号通貨を支えるブロックチェーンには興味があります。今回は、オープンソースのブロックチェーンプラットフォームであるEthereumを使って、ローカルネットワーク上で独自コインを実装してみたいと思います。

準備

ネットワーク 

Ethereumのネットワークには、いわゆるパブリックブロックチェーンと、テストネットワークがあります。さらにテストネットワークには、世界中のノードが参加できるModern testnetと、限られたノードのみが参加できるlocal private testnetがあります。本稿では、local private testnetを使用します。

クライアント

Ethereumのクライアントには様々なものがあります。本稿では、Ethereum Foundationが開発している、Go言語で実装されたクライアントgo-ethereum(Geth)を使用します。Macであれば、HomebrewでEthereumをインストールすることで利用できます。

$ brew tap ethereum/ethereum
$ brew install ethereum
$ geth version
Geth
Version: 1.7.3-stable
...

テストネットワークの構築

ローカル環境にテストネットワークを構築するためには、データ保存用のディレクトリと、ブロックチェーンの最初のブロックの情報を記したGenesisファイルが必要になります。GenesisファイルはJSON形式で記述します。テストネットワークなのでdifficultyは小さめにしてあります。

genesis.json
{
  "config": {
    "chainId": 5,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
  },
  "difficulty": "0x4000",
  "gasLimit": "0x8000000",
  "alloc": {}
}

Gethを初期化します。データ保存用のディレクトリはtestnetとしました。

$ mkdir testnet
$ geth --datadir testnet init genesis.json 

アカウントの作成

本稿では、独自のコインを発行することが目的です。コインをやりとりするために、アカウントを二人分作成します。アカウントは、gethコマンドで作成できます。

$ geth --datadir testnet account new
Your new account is locked with a password. Please give a password. 
Do not forget this password.
Passphrase: foobar01 # パスフレーズは画面に表示されません。
Repeat passphrase: foobar01 # パスフレーズは画面に表示されません。
Address: {12507a4a19b059d19a45156669c5adf3a2beacdb}

同じようにして「foobar02」というパスフレーズで、二人目のアカウントを作成しました。

Etherの採掘

Ethereum上で実行するアプリケーションを(スマート)コントラクトと呼びます。コントラクトを実行するためには、Ethereum上の暗号通貨であるEtherで、手数料(Gas Fee)を支払う必要があります。そこで、ローカルプライベートネットワークで、Etherを採掘します。採掘したEtherは、ローカルプライベートネットワークでのみ使用可能です。

Etherの採掘は、Gethのコンソール上で行います。「netowrkid」は予約済みの0〜3以外の数値を指定して下さい。「nodiscover」は他ノードから見つからないようにします。「maxpeers 0」は他ノードと接続しないようにします。

$ geth --networkid 123 --nodiscover --maxpeers 0 --datadir testnet console

コマンドを実行すると、Javascriptベースのコンソールが起動します。採掘をはじめましょう。採掘中は沢山メッセージが出力されます。

> miner.start(1)
...

適当なところで、止めましょう。メッセージが出力されていても気にせず、コンソールに停止コマンドを入力します。

> miner.stop()
...
# しばらくメッセージが出ることがありますが、良きところで止まってくれます。

先ほど作成したアカウントの残高を確認します。単位がetherではなくweiなのでとても大きな額が表示されます。採掘はこれで完了です。

> eth.getBalance(eth.accounts[0])
# とても大きな額

コントラクト指向プログラミング言語Solidity

本稿では、コントラクトの実装に、Solidityを使用します。コントラクトを実装するためのプログラミング言語には、他にSerpentなどがありますが、おそらくSolidityが最も人気があり、ネットから情報を得やすいと思います。Solidityは、Javascriptに似た文法を持っています。Macであれば、Homebrewでインストールできます。

$ brew install solidity
$ solc --version
solc, the solidity compiler commandline interface
Version: 0.4.19+commit.c4cbbb05.Darwin.appleclang

Hello, world

サンプルプログラムとして「Hello, world」を表示してみましょう。greetメソッドを呼び出すと「Hello, world」という文字列を返すだけのシンプルなものです。

hello.sol
pragma solidity ^0.4.16;

contract HelloWorld {
  function greet() public pure returns (string) {
    return 'Hello, world';
  }
}

コンパイルと実行

コンパイルはsolcコマンドで行います。

$ solc --bin --abi hello.sol

======= hello.sol:HelloWorld =======
Binary: # 長いので省略します。実行時に必要です。
Contract JSON ABI
# 長いので省略します。JSONが出力されます。実行時に必要です。

実行はGethのコンソールで行います。

> personal.unlockAccount(eth.accounts[0])
Unlock account 0x12507a4a19b059d19a45156669c5adf3a2beacdb
Passphrase: # アカウント作成時のパスフレーズを入力します。
true
> data = '0x' + '上記のコンパイル時に出力されたBinaryの部分をコピペします。'
> abi = 上記のコンパイル時に出力されたJSONをコピペします。
> contract = eth.contract(abi)
> HelloWorld = contract.new({from: eth.accounts[0], data: data, gas: 1000000})
...
# 「address: undefined」となっている場合は、miner.start()で採掘します。
> miner.start(1)
> HelloWorld.address
"0xed736a6d40c96ddf35088cb695c5bdbb192d8990"
> miner.stop()
> HelloWorld.greet.call()
"Hello, world"

無事にHello, worldが表示されました。

独自コインの実装

ブロックチェーン上に作られた通貨を、一般にトークン(Token)と呼びます。Ethereum上に実装されるべきトークンの仕様については、EIP-20 Token Standardという文書にまとめられています(以前はERC20と呼ばれていました)。本稿では、これらの仕様を満たすのは大変なので、シンプルに送金だけを実装します。

mcoin.sol
pragma solidity ^0.4.16;

contract MCoin {
  /**
   * mappingは、ハッシュの様なもので、
   * balanceOfは、address型をkeyとして、
   * uint256型の残高を表すvalueを持つ。
   * address型はアカウントのアドレスを扱う。
   */
  mapping (address => uint256) public balanceOf;

  /**
   * いわゆるコンストラクタ
   * 送金元の最初の残高を設定する。
   */
  function MCoin(uint256 _initialSupply) public {
    balanceOf[msg.sender] = _initialSupply;
  }

  /**
   * コインを_toに_valueだけ送金する。
   */
  function transfer(address _to, uint256 _value) public {
    /* 送金元の残高を減らして(残高チェックなどは省略)、 */
    balanceOf[msg.sender] -= _value;
    /* 送金先に加える。 */
    balanceOf[_to] += _value;
  }
}

Hello, worldの時と同様にコンパイルして、バイナリデータとabiを得ます。

$ solc --bin --abi mcoin.sol

======= mcoin.sol:MCoin =======
Binary: # 長いので省略します。実行時に使用します。
Contract JSON ABI
# 長いので省略します。実行時に使用します。

Gethのコンソール上で実行します。

> personal.unlockAccount(eth.accounts[0])
Unlock account 0x12507a4a19b059d19a45156669c5adf3a2beacdb
Passphrase: # アカウント作成時のパスフレーズを入力します。
true
> data = '0x' + '上記のコンパイル時に出力されたBinaryの部分をコピペします。'
> abi = 上記のコンパイル時に出力されたJSONをコピペします。
> contract = eth.contract(abi)
# 初期値は100コインにしてみました。
> MCoin = contract.new(100, {from: eth.accounts[0], data: data, gas: 1000000})
...
# 「address: undefined」となっている場合は、miner.start()で採掘します。
> miner.start(1)
...
> MCoin.address
"0xb843c36d0928fe0f035d48c0b28510de098d5286"
> miner.stop()
# 初期値がセットされてるか確認します。
> MCoin.balanceOf.call(eth.accounts[0])
100
# 10コイン送金します。
> MCoin.transfer.sendTransaction(eth.accounts[1], 10, {from: eth.accounts[0]})
> miner.start(1)
...
> miner.stop()
# 送金結果を確認します。
> MCoin.balanceOf.call(eth.accounts[0])
90
> MCoin.balanceOf.call(eth.accounts[1])
10

無事に送金できました!!

おわりに

記事を書き終えた後で、類似の入門記事が幾つかあることに気づきました...環境やバージョンによって手順などが微妙に異なるということで、ネットの海を汚すことをお許し下さい。参考までにリンクを掲載しておきます。1. は、Ethereum公式のもので、本稿を書く上で参考にしました。本稿では、ターミナル上で進めてきましたが、IDEを使ってコントラクトを実行するのが良いみたいですね^^;

  1. Create a cryptocurrency contract in Ethereum
  2. How to create a token/coin on Ethereum
  3. 最小構成のEthereum Tokenのprivatenetへの登録
  4. EthereumにGethを使ってオレオレトークンを発行するまで

Ethereumは、Solidityでコントラクトを作成することにより、ブロックチェーン上で色々なことができるので、アイディア次第で新しいことができそうです。

12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?