前回の記事で、Ethereumを利用したブロックチェーンのプライベートネットワークを、Gethで構築するところまでしました。
今回は、前回構築したプライベートネットワーク上で、「Ether」(イーサ)を送金してみたいと思います。
Ethereumには、ビットコインと同じ仮想通貨機能が実装されています。Etherとは、Ethereumにおける仮想通貨単位のことで、ビットコインでいうBTCに相当するものです。
この仮想通貨は、マイニングの報酬として得ることができます。また、今回は詳しく触れませんが、コントラクトを実行するために「Gas」と呼ばれる手数料をEtherで支払う必要があります。
送金に必要なアカウントの作成
それでは早速、送金するために必要なアカウント(正確には「EOAアカウント」)を作成しましょう。
まずはGethを起動します。
1 2 3 4 5 6 7 |
# geth --networkid "10" --nodiscover --datadir "/root/eth_private_net" console 2>> /root/eth_private_net/geth.log Welcome to the Geth JavaScript console! instance: Geth/v1.6.7-stable-ab5646c5/linux-amd64/go1.8.1 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 > |
コンソール画面になったら、早速アカウントをつくりましょう!
送金ということで、お金を送る側と受け取る側が必要なので、アカウントを2つ用意します。
personal.newAccount([アカウントのパスワード]) でアカウントを作成できます。
1 2 3 4 |
> personal.newAccount("AAAAAAAA") "0xb0490eae092b1a3e44bb313d52bacc49f6678efc" > personal.newAccount("BBBBBBBB") "0x6b8fc0fdb66f7d17f8b9dbfefcbbc12eab0c6eb3" |
作成した際に表示される文字列は、アカウントのアドレスです。作成したアカウントは、以下のコマンドで確認できます。
1 2 3 4 5 6 |
> eth.accounts ["0xb0490eae092b1a3e44bb313d52bacc49f6678efc", "0x6b8fc0fdb66f7d17f8b9dbfefcbbc12eab0c6eb3"] > eth.accounts[0] "0xb0490eae092b1a3e44bb313d52bacc49f6678efc" > eth.accounts[1] "0x6b8fc0fdb66f7d17f8b9dbfefcbbc12eab0c6eb3" |
また、ついでにEtherbase(マイニング成功時に報酬を受け取るアカウント)を確認しておきましょう。
1 2 |
> eth.coinbase "0xb0490eae092b1a3e44bb313d52bacc49f6678efc" |
デフォルトだと、Etherbaseにはeth.accounts[0]が設定されています。Etherbaseは、miner.setEtherbaseコマンドで変更することが可能です。
1 2 |
> miner.setEtherbase(eth.accounts[1]) true |
さて、早速送金したいと思います!先程作成したアカウントを以下のように定義し、AさんからBさんに送金してみます。
- eth.accounts[0]:Aさん(Etherbase)
- eth.accounts[1]:Bさん
その前に、送信元となるAさんの残高を確認してみましょう。
1 2 |
> eth.getBalance(eth.accounts[0]) 0 |
はい。そうですよね。無一文です。送りたくても送るお金が無いです。ということで、まずはお金(Ether)をゲットしましょう。
Etherのマイニング実行
冒頭でも書きましたが、Etherはマイニングの報酬として得ることができます。しばらくマイニングして、お金を貯めたいと思います。
マイニングは、miner.start([スレッド数])コマンドで開始します。引数で指定する「スレッド数」は、マイニングを何本のスレッドで同時実行するかを指定するパラメータで、指定しない場合はマシンのCPUコア数に依存します。
1 2 3 4 |
> miner.start() null > eth.mining true |
上記のように、eth.miningコマンドで、現在マイニング中かどうかが確認できます。trueが返ってきたので、マイニング中であることが確認できました。
それでは、このまましばらく放っておいて、Etherをゲットしましょう!途中、eth.blockNumberコマンドで、現在のブロック番号を取得してみます。
1 2 3 4 |
> eth.blockNumber 0 > eth.blockNumber 101 |
最初は0だったブロック番号も、しばらく放っておくとマイニングが進み、上の例では101までブロックが作成されました。それではマイニングを終了します。
1 2 |
> miner.stop() true |
では、この時点でのAさん(eth.accounts[0])の残高を確認してみます。
1 2 |
> eth.getBalance(eth.accounts[0]) 820000000000000000000 |
すごい!こんなに貯まりました!…が、実はeth.getBalance()コマンドで取得できる残高の単位は、「ether」ではなく「wei」という単位なのです。(1wei = 0.000000000000000001ether)
単位を「ether」に変換すると…
1 2 |
> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether") 820 |
となり、820etherをマイニングの報酬でゲットしたということになります。
Etherを送金する
それでは、マイニングしてEtherもゲットできたところで、送金してみたいと思います。
現在のAさん、Bさんの残高は以下のとおりです。
- Aさん(accounts[0]):820 ether
- Bさん(accounts[1]):0 ether
AさんからBさんに10ether送金したいと思います。まず、送信元となるAさんのアカウントのロックを解除します。
personal.unlockAccount([アカウントのアドレス], [パスワード]) コマンドでロックを解除できます。
1 2 |
> personal.unlockAccount(eth.accounts[0], "AAAAAAAA") true |
第三引数として、アンロックする時間(秒)を指定することも可能です。上記のように指定なしの場合、デフォルトは300秒となります。
ロックを解除したら、AさんからBさんに10ether送金します。
1 2 |
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(10, "ether")}) "0x03afd66b30ca25e5c3e717f4642a1418f8f9ce0c41f03c679ed2ca49b29c655a" |
コマンドを実行すると、トランザクションが生成され、そのトランザクションのIDが返却されます。
これで送金完了!と言いたいところですが、トランザクションは、ブロックに取り込まれたときにトランザクションの内容が実行されるので、まだブロックに取り込まれていない今の状態では送金が完了していません。実際に、Bさんの残高を確認してみると、まだ0であることが確認できます。
1 2 |
> eth.getBalance(eth.accounts[1]) 0 |
また、返却されたトランザクションIDを使ってトランザクション情報を確認してみると、blockNumberがnullであることも確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
> eth.getTransaction("0x03afd66b30ca25e5c3e717f4642a1418f8f9ce0c41f03c679ed2ca49b29c655a") { blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000", blockNumber: null, from: "0xb0490eae092b1a3e44bb313d52bacc49f6678efc", gas: 90000, gasPrice: 18000000000, hash: "0x03afd66b30ca25e5c3e717f4642a1418f8f9ce0c41f03c679ed2ca49b29c655a", input: "0x", nonce: 0, r: "0x6002cbee8cef283e29d31742a16e3d8ee86187c339c4f6a345c6173996a1344c", s: "0x5cefb57f95c9ab73ddcacb8e857f3f64b618a69dc6afaf6e8088b4fb13cb6489", to: "0x6b8fc0fdb66f7d17f8b9dbfefcbbc12eab0c6eb3", transactionIndex: 0, v: "0x1b", value: 10000000000000000000 } |
このトランザクションは今どこにあるのかというと、「保留中のトランザクション」として管理されています。保留中のトランザクション一覧は、eth.pendingTransactionsコマンドで確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
> eth.pendingTransactions [{ blockHash: null, blockNumber: null, from: "0xb0490eae092b1a3e44bb313d52bacc49f6678efc", gas: 90000, gasPrice: 18000000000, hash: "0x03afd66b30ca25e5c3e717f4642a1418f8f9ce0c41f03c679ed2ca49b29c655a", input: "0x", nonce: 0, r: "0x6002cbee8cef283e29d31742a16e3d8ee86187c339c4f6a345c6173996a1344c", s: "0x5cefb57f95c9ab73ddcacb8e857f3f64b618a69dc6afaf6e8088b4fb13cb6489", to: "0x6b8fc0fdb66f7d17f8b9dbfefcbbc12eab0c6eb3", transactionIndex: 0, v: "0x1b", value: 10000000000000000000 }] |
それでは、再度マイニングをして、新しいブロックを作成してみます。
1 2 |
> miner.start() null |
少し待って、再度、保留中のトランザクション一覧を確認してみます。
1 2 |
> eth.pendingTransactions [] |
保留中のトランザクション一覧が空っぽになったのを確認できたら、マイニングを終了します。
1 2 |
> miner.stop() true |
トランザクションIDを指定し、再度トランザクション情報を確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
> eth.getTransaction("0x03afd66b30ca25e5c3e717f4642a1418f8f9ce0c41f03c679ed2ca49b29c655a") { blockHash: "0xb03059a67a87edb38bce775cf89064bcf78164cf196cb801da935bc4a709723f", blockNumber: 165, from: "0xb0490eae092b1a3e44bb313d52bacc49f6678efc", gas: 90000, gasPrice: 18000000000, hash: "0x03afd66b30ca25e5c3e717f4642a1418f8f9ce0c41f03c679ed2ca49b29c655a", input: "0x", nonce: 0, r: "0x6002cbee8cef283e29d31742a16e3d8ee86187c339c4f6a345c6173996a1344c", s: "0x5cefb57f95c9ab73ddcacb8e857f3f64b618a69dc6afaf6e8088b4fb13cb6489", to: "0x6b8fc0fdb66f7d17f8b9dbfefcbbc12eab0c6eb3", transactionIndex: 0, v: "0x1b", value: 10000000000000000000 } |
今度はblockNumberが付与されました。Bさんの残高も確認してみます。
1 2 |
> web3.fromWei(eth.getBalance(eth.accounts[1]), "ether") 10 |
おー!Bさんに10ether送金できました!
まとめ
1つ1つコマンドを実行してみると、どんな風に送金が行われているかが具体的に理解しやすい気がします!
今回Etherをゲットするためにマイニングを実行しましたが、プライベートネットワークだからこんなに簡単にゲットできちゃうのです。パブリックなネットワークでは熾烈な競争が繰り広げられるのでしょう…!
実は、送金トランザクションをブロックに取り込むためにマイニングしている間にも、Aさんはマイニング報酬を受け取り続けています。そのため、最後にAさんの残高を確認すると、Bさんに送金しているにも関わらず、残高が増えていることが確認できると思います。
次は、スマートコントラクトについて書きたいと思います!
執筆者プロフィール
- 社内の開発プロジェクトの技術支援や、新技術の検証に従事しています。主にアプリケーション開発系支援担当で、Java&サーバサイドが得意です。最近は、サーバーレスonAWSを推進しています。