このサイトは、只今WEB業界で活躍中のデザイナー、プログラマーの方々の情報を集めたweb統合情報サイトです。

Archives Details

仮想通貨(暗号通貨)の作り方 その2 (Gethの使い方)

暗号通貨、ブロックチェーン

2018.05.20

この記事は最終更新日から1年以上が経過しています。

どもです。

今回は、前回のこちらの記事の続きとなります。

さて早速、仮想通貨を作成していきたいのですが、一からオリジナルの仕様で作成するとなると、それなりに大変で、時間もかかりそうなので、今回は比較的容易に作成出来る、Ethereumのスマートコントラクト開発を行なっていきたいと思います。

スマートコントラクト開発で人気のクライアントアプリ「Geth (Go Ethereum)」を使って作って行きたいと思います。

開発環境構築

Gethのインストール

Geth(Go Ethereum)はGo言語によって実装されたCUIクライアントになります。

GethをインストールすることでEthereumネットワークにフル・ノードとして参加して様々な事が実行できます。

こちらのページよりGethをダウンロードしましょう。

Geth (Go Ethereum) ダウンロードページ

https://geth.ethereum.org/downloads/

 

Macの場合はこちらをクリック、

Windowsの場合はこちらからそれぞれ環境にあったのをインストールします。

当方は、Macなので、Macでのインストール例となります。

先程のリンクよりダウンロードし、ファイルを解凍すると、gethのbinファイルが含まれているので、こちらをクリックでgethが起動します。

任意のフォルダに含める場合は、フォルダを作成、パーミッションを変更して、 gethのbinファイルを格納します。

$ sudo mkdir /任意のフォルダ/

 

ルート権限でのみ実行出来ない場合は権限を付与しましょう

$ sudo chmod 777 /任意のフォルダ/

 

パスを通す

.bash_profile 等のファイルにパスを通す為の記述を行います。

.bash_profile 等のファイル

export PATH=/任意のフォルダ/:$PATH

パスを適応

$ source ~/.bash_profile

パスが通ったかの確認

パスが通っているかwhichコマンドで確認

$ which geth

結果

/任意のフォルダ/geth

と表示すればオッケーです。

Homebrewを使って インストール

と、少々面倒なやり方でインストールしましたが、

macにHomebrewがインストールされていれば、以下のコマンドで簡単にインストールが行えます。

$ brew tap ethereum/ethereum
$ brew install ethereum

実際にgethコマンドが使用できるか確認。

$ geth --help

gethのヘルプコマンド(geth –help)で、色々とヘルプ情報が表示すればインストール成功です。

githubのレポジトリはこちらです。

github

https://github.com/ethereum/go-ethereum

 

初期化ファイル作成

インストールが完了しましたら、設定を行なっていきましょう。

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

・パブリック・ネットワーク (本番環境)

・プライベートネット (ローカル環境)

・テストネット (他の参加者も含んだ環境)

 

プライベート開発を行うために、ローカル環境に一番最初のブロックを作成します。

これは、Genesisブロックと言われ、jsonファイル形式でファイルを作成をしていきます。

ディレクトリの場所は任意の場所で問題ありません。

今回は、以下にディレクトリを設け、genesis. jsonを作成しました。

~/eth_private_net/

genesis.json

{
  "config": {
    "chainId": 15,
    "homesteadBlock": 0,
    "eip 155 Block": 0,
    "eip 158 Block": 0
  },
  "nonce": "0x0000000000000042",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "difficulty": "0x00",
  "alloc": {},
  "coinbase": "0x0000000000000000000000000000000000000000",
  "timestamp": "0x00",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "0x00",
  "gasLimit": "0x1312d00"
}

次のコマンドで、ブロック チェーンの初期化処理を行います。

–datadirデータ用のディレクトリinit genesisファイルを指定します。

 

$ geth --datadir ~/eth_private_net/ init ~/eth_private_net/genesis.json

以下の様に、Successfully wrote genesis state メッセージが、出力されれば初期化成功となります 。

結果

INFO [05-20|12:30:49] Successfully wrote genesis state  database=lightchaindata  hash=76d747…1a5e65

初期化のコマンドを実行すると、--datadirで指定したディレクトリ以下に、Gethで使用するディレクトリが新規で作成され、その中にgenesisブロックのブロックチェーン情報が保存されます。

ディレクトリを確認すると、以下の様に作成されているのが確認出来ます。

genesis.json
geth
keystore

Gethの起動

それでは、先程用意した、「eth_private_net」や「genesis. json」を用いて、Gethを起動していきます。

$ geth --networkid "15" --nodiscover --datadir "~/eth_private_net/" --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" --rpcapi "eth, net, web3, personal" --targetgaslimit "20000000" console 2>> ~/eth_private_net/geth_err.log

 

明示的にオプションに、ポート指定など行っていますが、省略も可能となっております。

省略した場合

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

 

上記のどちらのコマンドを入力、リターンを行い、「Welcome to the Geth JavaScript console!」のメッセージが表示され、コンソールが表示し、入力待ち状態になっていれば、Gethの起動成功となります。

Welcome to the Geth JavaScript console!
instance: Geth/v1.8.8-stable/darwin-amd64/go1.10.2
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

Gathコンソール

Gethを起動すると、対話式のコンソールが起動いたしますので、色々とコマンドを実行していきましょう。

 

ブロック確認

eth.getBlock(number)

Eth.getBlock Numberに任意のブロック高を指定すると、そのブロック高のブロック情報を表示することができます。

 

Genesisiブロック内容確認

引数に0を指定すれば、genesisブロックの確認が行えます。

先程用意した「genesis. json」が適応されているか確認しましょう。

eth.getBlock(0)

実行結果

{
  difficulty: 0,
  extraData: "0x00",
  gasLimit: 20000000,
  gasUsed: 0,
  hash: "0x76d747ec34337ec5677b1aba554769485e160663eee3c63486400bddc21a5e65",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 505,
  stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  timestamp: 0,
  totalDifficulty: 0,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

 

アカウント作成

Gethのコンソール上でGathコマンドを使って新規のアカウントを作成していきます。

EthereumにはEOA(Externally Owned Account)と、Contract2種類のアカウントが存在します。

今回は、EOAを新規に作成して行きます。

personal.newAccount("password")

 

 

以下の様にEOAアドレスが表示されればアカウント作成完了です。

personal.newAccount("password")

 

結果

"0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a"

 

 

あと、2つ程同様の作業で、作成しておきましょう。

作成完了しましたら、作成されたアカウントの確認を行なってみましょう。

 

インデックス指定で、アカウント確認

アカウントに関しては、「eth.accounts」に配列で格納されていますので、インデックスを指定することによって任意のアカウントを確認することができます。

eth.accounts[0]

結果には、EOAのアドレスが出力されます。

 

全てのアカウントを確認

作成さえた全てのアカウントを確認したい場合は、以下の様に指定すれば確認することができます。

eth.accounts

結果

["0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a", "0xb985896b8b53f0323bd3019bc70060521e5bb00f", "0x52e48b0e2903a960937577021048440293f3f011"]

 

今回は上記の3つのアカウントを作成しております。

Coinbase(etherbase)アカウント

続いて、Coinbase(etherbase)アカウントの設定を行なっていきましょう。

Coinbase(etherbase)アカウントとは、各ノードで採掘を行う際にその報酬を紐づけるEOAのアドレスとなります。

以下のコマンドで、coinbase(etherbase)アカウントのEOAアドレスを確認できます。

デフォルトでは、インデックス0のアカウントに設定されております。

eth.coinbase

 

結果

"0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a"

 

 

setEtherbase」で、変更することも可能です。

miner.setEtherbase(eth.accounts[1])

結果

true

今回は、Coinbase(etherbase)アカウントは、eth.accounts[0]のまま進めていきます。

 

マイニング

作成したEOAのアドレスがcoinbase(etherbase)としてセットされていれば、etherの採掘が可能となります。

採掘のコマンドは以下のコマンドで実行出来ます。

miner.start(スレッド数)

引数には、マイニングを行うスレッド数の指定をします。

特に指定がない場合は、動作環境のCPUコア数に設定されます。

 

miner.start(2)

結果

null
マイニング確認

マイニング中であるかどうかの確認になります。

trueが返却されましたら、マイニング中になります。

eth.mining

結果

true
マイニング終了

採掘の終了は以下のコマンドで行えます。

miner.stop()

結果

true

今回は、止めずにそのまま進めます。

採掘状況の確認

採掘を開始するとブロックが生み出されます。

現在のブロック高の確認を行うには以下のコマンドを実行します。

eth.blockNumber

結果

164

といったように、ブロックが採掘されていることが確認できます。

今回の場合、164個のブロックが採掘されている、結果が出力されました。

残高を確認

それでは、採掘で獲得したcoinbase(etherbase)の残高確認を行なって見ましょう。

アカウント作成時は0なので、0以上になっていればマイニング成功となります。

eth.getBalance(eth.accounts[0])

結果

1.1e+21
eth.getBalance(eth.accounts[1])

結果

0

coinbaseに紐づいたアカウントに採掘の報酬が与えられているのがわかります。

eth.getBalance(address)は「wei」の単位で持ち高が表示されますので、とても大きな数字が表示したかと思います。

以下の変換用のコマンドを使うことでetherの単位で表示することも可能です。

web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")

結果

1195

 

ロック解除

続いて、送金を行いたいのですが、アカウントがロックされている状態なので、アカウント生成時に設定したパスワードを入力してアカウントロックを解除しましょう。

 

personal.unlockAccount(eth.accounts[0])
personal.unlockAccount(eth.accounts[0])
Unlock account 0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a
Passphrase:

コマンドを入力すると、パスワードの入力を求められます。

アカウント作成時に指定した「password」を入力します。

結果

true

 

trueが返却されたら、解除成功となります。

 

プライベートのテスト環境なので、毎度入力するのは少し手間がかかりますので、Geth起動時に解除する方法もあります。

以下の様に設定したパスワードを記述したファイルを作成します。

アカウント毎に改行区切りで記述していきます。

Geth起動時作成したファイルを指定すれば、アカウントロックが解除した状態で起動できます。

 

各アカウントのEOSアドレスが必要となっておきますので、表示させてメモしておきます。

eth.accounts

 

結果

["0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a", "0xb985896b8b53f0323bd3019bc70060521e5bb00f", "0x52e48b0e2903a960937577021048440293f3f011"]

 

 

Gethの終了

一度、起動しているGethを終了させます。

exit

eth_priavate_netに、新たにパスワード読み込み用のファイルを作成。

 

password.txt

password
password
password

起動時にパスワード解除するオプション

--unlock アンロックするアカウントアドレス --password "パスワードファイルのパス"

上記のオプションを付与した形で、Gethを起動すればアカウントロックが解除した状態で起動できます。

複数のアカウントに適応する場合は、カンマ区切りでアドレスを指定します。

先程、メモしておいた各アカウントのEOSアドレスをオプション指定して、Gethを起動させていきます。

 

$ geth --networkid "15" --nodiscover --datadir "~/eth_private_net" --rpc --rpcaddr "localhost" --rpcport "8545" --rpccorsdomain "*" --rpcapi "eth,net,web3,personal" --targetgaslimit "20000000" --unlock 0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a,0xb985896b8b53f0323bd3019bc70060521e5bb00f,0x52e48b0e2903a960937577021048440293f3f011 --password "password.txt" console 2>> ~/eth_private_net/geth_err.log [code]


起動出来ましたら、再びマイニングを開始します。
[code]miner.start(2)

 

送金

それでは、マイニングで得たEtherの送金を行なって見ましょう。

2つ目に作成したアカウントに、5 Ether送金して見ます。

eth.sendTransaction({ from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(5, "ether")})

結果

"0xce67645e3b3234c1cf82ec47c2cd919c969ce2a5939454974c0a3395017b9c45"

 

 

エラーが出ず、送金に成功しましたらマイニングを行いトランザクションを発行しましょう。

 

トランザクション確認

先ほどのトランザクションハッシュを元にトランザクションの確認を行います。

eth.getTransaction関数の引数に、トランザクションハッシュを指定し、トランザクションの中身を確認していきます。

eth.getTransaction('0xce67645e3b3234c1cf82ec47c2cd919c969ce2a5939454974c0a3395017b9c45')

 

結果

{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0xce67645e3b3234c1cf82ec47c2cd919c969ce2a5939454974c0a3395017b9c45",
  input: "0x",
  nonce: 0,
  r: "0xa4b7f915d52ebce2490c3fecc98e38ac126a2dcd967212ef58913f8127a7de4e",
  s: "0x4da560e57e60829bd160adf0f840eba851db84758b45487276e817c97074a535",
  to: "0xb985896b8b53f0323bd3019bc70060521e5bb00f",
  transactionIndex: 0,
  v: 0x1b",
  value: 5000000000000000000
}

fromに送信元アドレスのeth.accounts[0]がひょうじされ、 toに送信先アドレスである、eth.accounts[1] が表示されているかと思います。

valueは送金額で、「5000000000000000000」と大変大きな数値となっておりますが、表示が「wei」なので、etherに換算する と 5etherとなり、想定通りのトランザクションを発行出来ているのが確認できるかと思います。

続いて eth.getTransactionReceipt関数を実行して、トランザクションのレシートを表示させます。

引数に、トランザクションハッシュを指定することによって、 該当するトランザクションのレシートを表示させることが出来ます。トランザクションのレシートは、ブロックに取り込まれると発行されます。

「null」が返却された場合は、まだブロックに取り込まれていない状態となりますので、少し待つ必要がありますが、テスト環境だと15秒もあれば取り込まれるので、いくら待っても発行されない場合は、マイニングを開始していないとか他の原因を見たほうが良さそうです。

 

eth.getTransactionReceipt('0xce67645e3b3234c1cf82ec47c2cd919c969ce2a5939454974c0a3395017b9c45')

結果

{
  blockHash: "0xdaeee3a7bcc05dbbd959e12b690e684dc7100d475abf2b0140a3fa28fe2376e1",
  blockNumber: 640,
  contractAddress: <b>null</b>,
  cumulativeGasUsed: 21000,
  from: "0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a",
  gasUsed: 21000,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0x4296825f589b786f15211217fda15d358a8d34032a786ee4565941b7348acfbd",
  to: "0xb985896b8b53f0323bd3019bc70060521e5bb00f",
  transactionHash: "0xce67645e3b3234c1cf82ec47c2cd919c969ce2a5939454974c0a3395017b9c45",
  transactionIndex: 0
}

 

上記の結果のblockNumberを見ると、640ブロックで取り込まれた事が確認できます。

その他色々と項目がありますが、一旦置いて、残高が更新されたか確認していきます。

 

残高確認

eth.accounts[1]の残高確認を行なっていきます。

web3.fromWei( eth.getBalance( eth.accounts[1]), "ether")

結果

5

eth.accounts[1]のアカウントに、5ether送られてきているのが確認できました。

続けて、今度は10ether送金してみたいと思います。

 

送金

eth.sendTransaction({ from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(10, "ether")})

結果

"0x3dd23d01baf6f433ef8c4625d49b7162b62056f914c1397f91131adb5641c228"

トランザクションのレシートの確認

> eth.getTransactionReceipt('0x3dd23d01baf6f433ef8c4625d49b7162b62056f914c1397f91131adb5641c228')

結果

{
  blockHash: "0x169157ec393f9c4ee345885e096f37b9b0047684b7ca08ad2e693fceb7ef64c9",
  blockNumber: 1181,
  contractAddress: <b>null</b>,
  cumulativeGasUsed: 21000,
  from: "0x5db7d11cafb9687131d37cc4de70a7ca97c61c0a",
  gasUsed: 21000,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0x4694ccbbc4b47d3581fcbf350ccac955c26a41574e46231825c9edea9c8ce9a7",
  to: "0xb985896b8b53f0323bd3019bc70060521e5bb00f",
  transactionHash: "0x3dd23d01baf6f433ef8c4625d49b7162b62056f914c1397f91131adb5641c228",
  transactionIndex: 0
}

残高確認

web3.fromWei(eth.getBalance(eth.accounts[1]), "ether")

結果

15

前回の5etherと今回の10etherで、15etherになっているのが確認出来たかと思います。

 

ブロック高指定の残高確認

web3.fromWeiコマンドは、トランザクションのレシートで表示していた、アカウントと、ブロック高を引数にすることによって、ブロック高時点の残高を確認することも出来ます。

web3.fromWei(eth.getBalance(eth.accounts[1],1181),"ether")

結果

15

一つの前のブロックを指定

> web3.fromWei(eth.getBalance(eth.accounts[1],1180),"ether")
5

1180から1181のブロックで、5から15に増えたのが確認できたかと思います。

 

Geth終了

exit

Gethの終了コマンドは「exit」で終了することが出来ます。

 

と言った感じで、Gethコンソールの扱いをご紹介させて頂きました。
次回は、Solidityを用いてスマートコントラクト開発を行っていきましょう。

ではではぁ。

Comment

Related Article

SolidityとEthereumによる実践スマートコントラクト開発 書評 ~ 再構築

2023.02.10

Geth (Go Ethereum)でリクエスト送信「Invalid host specified」エラー対処

2022.03.06

Geth (Go Ethereum) API 変更点

2022.03.05

仮想通貨(暗号通貨)の作り方 その2 (Gethの使い方)

2018.05.20

$PAC (パックコイン)Macでマスターノードを建てる方法

2018.05.14

仮想通貨(暗号通貨)の作り方 その1

2018.04.09

CATEGORY LIST

LATEST NEWS

Rust - Actix Web mongo ユーザー登録 JWT認証

Rust

2024.03.24

Rust - Actix Web JWT 認証認可 APIの作成

Rust

2024.02.25

Rust - Actix Web × JSON 静的ファイルをAPIで返却

Rust

2024.01.19

Rust - Actix Web × MongoDB環境をサクッと起動

Rust

2024.01.18

5分で学ぶ RustでWave Function Collapse (波動関数崩壊アルゴリズム)

Rust

2024.01.15

LLaMAモデル GGMLフォーマット(llama.cpp)をRustフレームワーク Leptosを用いて M1MacMiniでサクッと動かす。

Rust

2024.01.11

2024年 狙っているモバイルノートPC

tool

2024.01.07

MacOS XcodeにSDL2を追加

tool

2023.12.26

php 7.4にアップデート

PHP

2023.12.24

5分で覚える Flutter Flameで作る Wave Function Collapse - 波動関数崩壊アルゴリズム

AI・Bot・algorithm

2023.12.20

Flutter - Flameでゲーム作成 (キャラクターの移動)

Flutter

2023.07.23

Flutterで作る ChatGPT Prompt Manager

Flutter

2023.07.12

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

WEBデザイナーの、WEBデザイナーによる、WEBデザイナーの為のサイト。「みんなで書こう!」と仲間を募ってみたが、結局書くのは自分だけとなってしまいました。日々のメモを綴っていきます。

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

MAD CITY 北九州市で生まれ育つ。20代はバンド活動に明け暮れ、ふと「webデザイナーになりたい。」と思い、デジタルハリウッド福岡校入学。卒業後、数々の賞を受賞、web業界をざわつかせる。
現在、主に、ゲーム制作中心に港区六本木界隈で活動中。

FOLLOW US