メインコンテンツへスキップ

Python開発者のためのイーサリアム入門 パート1

python
web3.py
初級
マーク・ガロー
2020年9月8日
22 分で読めます

イーサリアムについて耳にして、その奥深い世界に足を踏み入れる準備はできましたか?この記事では、ブロックチェーンの基本を簡単に説明した後、シミュレートされたイーサリアムノードと対話して、ブロックデータの読み取り、アカウント残高の確認、トランザクションの送信を行います。その過程で、従来のアプリ構築方法とこの新しい分散型パラダイムの違いを強調します。

(緩やかな)前提条件

この記事は、幅広い開発者が理解できるように書かれています。Pythonツールを使用しますが、これらはアイデアを伝えるための手段にすぎません。Python開発者でなくても問題ありません。ただし、イーサリアム特有の部分にすぐに移れるように、あなたがすでに知っていることについていくつか前提を置きます。

前提条件:

  • ターミナルを操作できること
  • Pythonコードを数行書いたことがあること
  • マシンにPythonバージョン3.6以上がインストールされていること(仮想環境 (opens in a new tab)の使用を強く推奨します)
  • Pythonのパッケージインストーラーであるpipを使用したことがあること 繰り返しになりますが、これらのいずれかに当てはまらない場合や、この記事のコードを再現する予定がない場合でも、おそらく問題なく読み進めることができます。

ブロックチェーンの概要

イーサリアムを説明する方法はたくさんありますが、その中心にあるのはブロックチェーンです。ブロックチェーンは一連のブロックで構成されているため、そこから始めましょう。最も簡単に言えば、イーサリアムブロックチェーン上の各ブロックは、いくつかのメタデータとトランザクションのリストにすぎません。JSON形式では、次のようになります。

{
   "number": 1234567,
   "hash": "0xabc123...",
   "parentHash": "0xdef456...",
   ...,
   "transactions": [...]
}

ブロックには、その前のブロックへの参照があります。parentHashは単に前のブロックのハッシュです。

注:イーサリアムは、固定サイズの値(「ハッシュ」)を生成するためにハッシュ関数を定期的に使用します。ハッシュはイーサリアムで重要な役割を果たしますが、今のところは一意のIDと考えて差し支えありません。

A diagram depicting a blockchain including the data inside  each block

ブロックチェーンは本質的に連結リストです。各ブロックには前のブロックへの参照があります。

このデータ構造は目新しいものではありませんが、ネットワークを管理するルール(つまり、ピア・ツー・ピアプロトコル)は斬新です。中央権力は存在しません。ピアのネットワークは、ネットワークを維持するために協力し、次のブロックにどのトランザクションを含めるかを決定するために競争しなければなりません。したがって、友人に送金したい場合は、そのトランザクションをネットワークにブロードキャストし、それが次のブロックに含まれるのを待つ必要があります。

ブロックチェーンが、あるユーザーから別のユーザーへ本当にお金が送られたことを検証する唯一の方法は、そのブロックチェーンにネイティブな(つまり、そのブロックチェーンによって作成および管理される)通貨を使用することです。イーサリアムでは、この通貨はイーサと呼ばれ、イーサリアムブロックチェーンにはアカウント残高の唯一の公式記録が含まれています。

新しいパラダイム

この新しい分散型技術スタックは、新しい開発者ツールを生み出しました。このようなツールは多くのプログラミング言語に存在しますが、ここではPythonの観点から見ていきます。繰り返しますが、Pythonがあなたの好む言語でなくても、理解するのにそれほど苦労はしないはずです。

イーサリアムと対話したいPython開発者は、Web3.py (opens in a new tab)に手を伸ばす可能性が高いでしょう。Web3.pyは、イーサリアムノードに接続し、そこからデータを送受信する方法を大幅に簡素化するライブラリです。

注:「イーサリアムノード」と「イーサリアムクライアント」は同義語として使用されます。どちらの場合も、イーサリアムネットワークの参加者が実行するソフトウェアを指します。このソフトウェアは、ブロックデータの読み取り、チェーンに新しいブロックが追加されたときの更新の受信、新しいトランザクションのブロードキャストなどを行うことができます。厳密には、クライアントはソフトウェアであり、ノードはそのソフトウェアを実行しているコンピューターです。

イーサリアムクライアントは、IPC (opens in a new tab)、HTTP、またはWebsockets経由で到達できるように構成できるため、Web3.pyはこの構成を反映する必要があります。Web3.pyは、これらの接続オプションをプロバイダーと呼びます。Web3.pyインスタンスをノードにリンクするには、3つのプロバイダーのいずれかを選択する必要があります。

A diagram showing how web3.py uses IPC to connect your application to an Ethereum node

イーサリアムノードとWeb3.pyが同じプロトコル(この図ではIPCなど)を介して通信するように構成します。

Web3.pyが適切に構成されると、ブロックチェーンとの対話を開始できます。今後のプレビューとして、Web3.pyの使用例をいくつか紹介します。

# ブロックデータを読み込む:
w3.eth.get_block('latest')

# トランザクションを送信する:
w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})

インストール

このチュートリアルでは、Pythonインタープリター内でのみ作業します。ディレクトリ、ファイル、クラス、関数は作成しません。

注:以下の例では、$で始まるコマンドはターミナルで実行することを意図しています。($は入力しないでください。これは単に行の始まりを示しているだけです。)

まず、探索しやすいユーザーフレンドリーな環境のためにIPython (opens in a new tab)をインストールします。IPythonはタブ補完などの機能を提供しており、Web3.py内で何が可能かをはるかに簡単に確認できます。

pip install ipython

Web3.pyはweb3という名前で公開されています。次のようにインストールします。

pip install web3

もう1つ、後でブロックチェーンをシミュレートしますが、これにはさらにいくつかの依存関係が必要です。これらは次のようにインストールできます。

pip install 'web3[tester]'

これで準備完了です!

注:web3[tester]パッケージはPython 3.10.xxまで動作します。

サンドボックスの立ち上げ

ターミナルでipythonを実行して、新しいPython環境を開きます。これはpythonを実行するのと同じですが、より多くの便利な機能が付属しています。

ipython

これにより、実行しているPythonとIPythonのバージョンに関する情報が出力され、入力を待つプロンプトが表示されるはずです。

In [1]:

現在、対話型のPythonシェルを見ています。基本的には、遊ぶためのサンドボックスです。ここまで来たら、Web3.pyをインポートする時間です。

In [1]: from web3 import Web3

Web3モジュールの紹介

イーサリアムへのゲートウェイであることに加えて、Web3 (opens in a new tab)モジュールはいくつかの便利な機能を提供します。いくつか見てみましょう。

イーサリアムアプリケーションでは、通常、通貨の単位を変換する必要があります。Web3モジュールは、まさにこのためのヘルパーメソッドをいくつか提供しています。from_wei (opens in a new tab)to_wei (opens in a new tab)です。

注:コンピューターは小数の計算が苦手なことで有名です。これを回避するために、開発者はしばしばドル金額をセントで保存します。たとえば、価格が5.99ドルのアイテムは、データベースに599として保存される場合があります。

イーサでのトランザクションを処理する場合にも、同様のパターンが使用されます。ただし、イーサには小数点以下2桁ではなく、18桁あります!イーサの最小単位はWeiと呼ばれるため、トランザクションを送信する際に指定されるのはこの値です。

1イーサ = 1000000000000000000 Wei

1 Wei = 0.000000000000000001イーサ

いくつかの値をWeiに、またはWeiから変換してみてください。イーサとWeiの間の多くの単位には名前がある (opens in a new tab)ことに注意してください。その中でよく知られているものの1つがGweiです。これは、トランザクション手数料がしばしばこの単位で表されるためです。

In [2]: Web3.to_wei(1, 'ether')
Out[2]: 1000000000000000000

In [3]: Web3.from_wei(500000000, 'gwei')
Out[3]: Decimal('0.5')

Web3モジュールのその他のユーティリティメソッドには、データ形式コンバーター(例:toHex (opens in a new tab))、アドレスヘルパー(例:isAddress (opens in a new tab))、およびハッシュ関数(例:keccak (opens in a new tab))が含まれます。これらの多くは、このシリーズの後半で取り上げます。利用可能なすべてのメソッドとプロパティを表示するには、Web3.と入力し、ピリオドの後にTabキーを2回押してIPythonの自動補完を利用します。

チェーンとの対話

便利なメソッドは素晴らしいですが、ブロックチェーンに進みましょう。次のステップは、イーサリアムノードと通信するようにWeb3.pyを構成することです。ここでは、IPC、HTTP、またはWebsocketプロバイダーを使用するオプションがあります。

この方法には進みませんが、HTTPプロバイダーを使用した完全なワークフローの例は次のようになります。

  • イーサリアムノード(例:Geth (opens in a new tab))をダウンロードします。
  • 1つのターミナルウィンドウでGethを起動し、ネットワークを同期するのを待ちます。デフォルトのHTTPポートは8545ですが、構成可能です。
  • Web3.pyに、localhost:8545でHTTP経由でノードに接続するように指示します。 w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • w3インスタンスを使用してノードと対話します。

これは「実際の」方法の1つですが、同期プロセスには何時間もかかり、単に開発環境が必要な場合には不要です。Web3.pyは、この目的のために4番目のプロバイダーであるEthereumTesterProviderを公開しています。このテスタープロバイダーは、緩和された権限と遊ぶための偽の通貨を備えたシミュレートされたイーサリアムノードにリンクします。

A diagram showing the EthereumTesterProvider linking your web3.py application to a simulated Ethereum node

EthereumTesterProviderはシミュレートされたノードに接続し、迅速な開発環境に便利です。

そのシミュレートされたノードはeth-tester (opens in a new tab)と呼ばれ、pip install web3[tester]コマンドの一部としてインストールしました。このテスタープロバイダーを使用するようにWeb3.pyを構成するのは、次のように簡単です。

In [4]: w3 = Web3(Web3.EthereumTesterProvider())

これでチェーンをサーフィンする準備ができました!そんな言葉はありません。私が今作っただけです。簡単なツアーに出かけましょう。

簡単なツアー

まず最初に、動作確認(サニティチェック)を行います。

In [5]: w3.is_connected()
Out[5]: True

テスタープロバイダーを使用しているため、これはあまり価値のあるテストではありませんが、失敗した場合は、w3変数をインスタンス化するときに何かを間違って入力した可能性があります。内側の括弧、つまりWeb3.EthereumTesterProvider()を含めたことを再確認してください。

ツアーの目的地その1:アカウント

便宜上、テスタープロバイダーはいくつかのアカウントを作成し、テスト用のイーサを事前にロードしています。

まず、それらのアカウントのリストを見てみましょう。

In [6]: w3.eth.accounts
Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]

このコマンドを実行すると、0xで始まる10個の文字列のリストが表示されるはずです。それぞれがパブリックアドレスであり、ある意味で当座預金口座の口座番号に似ています。イーサを送金したい人にこのアドレスを提供します。

前述のように、テスタープロバイダーはこれらの各アカウントにテスト用のイーサを事前にロードしています。最初のアカウントにいくら入っているか調べてみましょう。

In [7]: w3.eth.get_balance(w3.eth.accounts[0])
Out[7]: 1000000000000000000000000

ゼロがたくさんありますね!偽の銀行に行って大笑いする前に、先ほどの通貨の単位に関するレッスンを思い出してください。イーサの値は最小単位であるWeiで表されます。それをイーサに変換します。

In [8]: w3.from_wei(1000000000000000000000000, 'ether')
Out[8]: Decimal('1000000')

100万テストイーサ。それでも悪くありません。

ツアーの目的地その2:ブロックデータ

このシミュレートされたブロックチェーンの状態を覗いてみましょう。

In [9]: w3.eth.get_block('latest')
Out[9]: AttributeDict({
   'number': 0,
   'hash': HexBytes('0x9469878...'),
   'parentHash': HexBytes('0x0000000...'),
   ...
   'transactions': []
})

ブロックに関する多くの情報が返されますが、ここで指摘しておくべきことがいくつかあります。

  • ブロック番号はゼロです。テスタープロバイダーを構成したのがどれほど前であっても関係ありません。12秒ごとに新しいブロックを追加する実際のイーサリアムネットワークとは異なり、このシミュレーションは、あなたが何か作業を与えるまで待機します。
  • transactionsは空のリストです。理由は同じで、まだ何もしていないからです。この最初のブロックは、チェーンを開始するためだけの空のブロックです。
  • parentHashが単なる空のバイトの集まりであることに注目してください。これは、チェーンの最初のブロック、別名ジェネシス・ブロックであることを意味します。

ツアーの目的地その3:トランザクション

保留中のトランザクションが発生するまでブロックゼロで立ち往生しているので、トランザクションを1つ与えてみましょう。あるアカウントから別のアカウントへ、いくつかのテストイーサを送金します。

In [10]: tx_hash = w3.eth.send_transaction({
   'from': w3.eth.accounts[0],
   'to': w3.eth.accounts[1],
   'value': w3.to_wei(3, 'ether'),
   'gas': 21000
})

通常、ここでトランザクションが新しいブロックに含まれるまで数秒待ちます。完全なプロセスは次のようになります。

  1. トランザクションを送信し、トランザクション・ハッシュを保持します。トランザクションを含むブロックが作成されてブロードキャストされるまで、トランザクションは「保留中」です。 tx_hash = w3.eth.send_transaction({ … })
  2. トランザクションがブロックに含まれるのを待ちます。 w3.eth.wait_for_transaction_receipt(tx_hash)
  3. アプリケーションロジックを続行します。成功したトランザクションを表示するには: w3.eth.get_transaction(tx_hash)

シミュレートされた環境では、トランザクションが新しいブロックに即座に追加されるため、すぐにトランザクションを表示できます。

ここには見覚えのある詳細がいくつか表示されます。fromto、およびvalueフィールドは、send_transaction呼び出しの入力と一致するはずです。もう1つ安心できる点は、このトランザクションがブロック番号1内の最初のトランザクション('transactionIndex': 0)として含まれていることです。

また、関係する2つのアカウントの残高を確認することで、このトランザクションの成功を簡単に検証できます。3イーサがあるアカウントから別のアカウントへ移動しているはずです。

In [12]: w3.eth.get_balance(w3.eth.accounts[0])
Out[12]: 999996999979000000000000

In [13]: w3.eth.get_balance(w3.eth.accounts[1])
Out[13]: 1000003000000000000000000

後者は良さそうです!残高が1,000,000イーサから1,000,003イーサになりました。しかし、最初のアカウントはどうなったのでしょうか?3イーサよりわずかに多く失っているようです。悲しいかな、人生に無料のものはなく、イーサリアムのパブリックネットワークを使用するには、ピアのサポートの役割に対して報酬を支払う必要があります。トランザクションを送信したアカウントから少額のトランザクション手数料が差し引かれました。この手数料は、消費されたガス量(ETH送金の場合は21000単位のガス)に、ネットワークのアクティビティに応じて変動する基本料金と、トランザクションをブロックに含めるバリデータに支払われるチップを足したものを掛けた金額です。

ガスの詳細

注:パブリックネットワークでは、トランザクション手数料はネットワークの需要とトランザクションをどれだけ早く処理したいかに基づいて変動します。手数料の計算方法の内訳に興味がある場合は、トランザクションがブロックにどのように含まれるかに関する私の以前の記事を参照してください。

一息つきましょう

しばらく続けてきたので、この辺りで休憩するのが良さそうです。奥深い世界はまだ続いており、このシリーズのパート2で引き続き探索していきます。今後登場する概念:実際のノードへの接続、スマートコントラクト、トークン。追加の質問はありますか?ぜひ教えてください!あなたのフィードバックが、今後の方向性に影響を与えます。ツイッター (opens in a new tab)でのリクエストも歓迎します。