はじめに
Python + Web3.pyでEthereumを学習する記事、その3です。
その2では、「Ethereumの送金」を実施しました。その3では、「スマートコントラクト関数のデプロイ(実装)と呼び出し」を行っていきます!
事前準備
Node.jsのインストール
さて、今回は「Truffle」とよばれるイーサリアム開発用のフレームワークを使います。Truffleを使うためには、Node.jsというJavaScript実行環境をまずインストールすることになります。以下のサイトより、ご利用のOSのLTS推奨版をインストールしましょう。
Truffleのインストール
Truffleをインストールするには、node.jsをインストール完了後に、以下のコマンドを入力すればOKです。
npm install -g truffle
もしWindowsでのインストール時にエラー「このシステムではスクリプトの実行が無効になっているため…」というメッセージが表示される場合は、PowerShellを「管理者で実行」の上、以下のコマンドでスクリプト実行の許可をしましょう。
Set-ExecutionPolicy RemoteSigned
この実行により、「ローカルに保存しているファイルは実行可能で、インターネットからダウンロードしたものは署名のあるもののみ実行許可」のモードになるので、Truffleがインストール可能になるはずです。
スマートコントラクトのデプロイ
プロジェクトの作成・初期化
プロジェクトの作成のため、まずは「greeter」というフォルダ(プロジェクトフォルダ)を作りましょう。そのフォルダにて、以下のコマンドを打ち、プロジェクトを作成します。
truffle init
すると、フォルダ内に、「build」「contracts」「migrations」「test」の4つのフォルダが生成されていると思います。
スマートコントラクト関数の作成
さて、いよいよsolidityで記述されたスマートコントラクト関数本体を作ります。
pragma solidity ^0.5.7;
contract greeter{
string greeting;
function greet(string memory _greeting)public {
greeting=_greeting;
}
function getGreeting() public view returns(string memory) {
return greeting;
}
}
内容としては、「greeter」なるコントラクト内に「greet」メソッド(入力された文字をコントラクトに記憶する)、「getGreeting」メソッド(コントラクトに記憶された文字列を返す)の2つが定義されているのがわかりますね。
上記のスクリプトを「greeter.sol」というファイル名で、さきほど作成されたフォルダ「contracts」の中にいれておきましょう。
スマートコントラクト関数のコンパイル
次に、プロジェクトフォルダにて、以下のコマンドを打ち、スマートコントラクト関数をコンパイルします。
truffle compile
このコマンドにより、プロジェクトフォルダ内の「contracts」内solファイルをコンパイルを行い、「build」フォルダにファイル「greeter.json」が出力されます。
スマートコントラクトのデプロイ
これで準備は整ったので、いよいよスマートコントラクトのデプロイを行います。
# 1. Import Module
import json
from web3 import Web3, HTTPProvider
from web3.contract import ConciseContract
# 2. Access Ganache local server
web3 = Web3(HTTPProvider("HTTP://127.0.0.1:7545"))
print(web3.isConnected())
# 3. Account Address, private key
key = "Your-ganache-private-Key"
acct = web3.eth.account.privateKeyToAccount(key)
# 4. Set smart contract information
truffleFile = json.load(open('./build/contracts/greeter.json'))
abi = truffleFile['abi']
bytecode = truffleFile['bytecode']
contract= web3.eth.contract(bytecode=bytecode, abi=abi)
# 5. Building transaction information
construct_txn = contract.constructor().buildTransaction({
'from': acct.address,
'nonce': web3.eth.getTransactionCount(acct.address),
'gas': 1728712,
'gasPrice': web3.toWei('21', 'gwei')})
# 6. Send Transaction
signed = acct.signTransaction(construct_txn)
tx_hash = web3.eth.sendRawTransaction(signed.rawTransaction)
print(tx_hash.hex())
# 7. Display contract address
tx_receipt = web3.eth.waitForTransactionReceipt(tx_hash)
print("Contract Deployed At:", tx_receipt['contractAddress'])
2.について。今回もGanacheを使うためにGanacheを起動しておき、アクセスするURLを記載しています。
3. にはGanacheの任意のアドレスのプライベートキーを入力しておきます。アドレスは、プライベートキーから算出しています。
4. Truffleによって生成されたjsonファイルをコントラクトとしてデプロイ可能な状態にします。
5. こちらも前回同様、トランザクションに必要なアドレス、ナンス値、ガスを設定します。
6. トランザクションを実行し、そのハッシュ値を取得します。
7. 生成されたコントラクトアドレスを取得、表示します。
問題なく出力されれば、以下のような出力がされます。
True
0xd7603d1c9b190b54b18ac6238a31991cf59c82eca6219db65e51bce0a526da6d
Contract Deployed At: 0xD3C53651Fbd2A8a1Efe30504CC452F34e435A47F
以上で、ブロックチェーンにコントラクトをデプロイ(実装)することができました!
スマートコントラクトの状態変更
実は、上記の状態のままでは、スマートコントラクトを呼び出しても、何も実行されません。というのも、greet()関数を一回も呼び出していないため、その関数に何も記録されていないためです。
ということで、以下のスクリプトを実行し、スマートコントラクトの関数に文字列をセットします。
# 1. Import Module
import json
from web3 import Web3, HTTPProvider
from web3.contract import ConciseContract
# 2. Access Ganache local server
web3 = Web3(HTTPProvider("HTTP://127.0.0.1:7545"))
print(web3.isConnected())
# 3. Account Address, private key
key = "Your-ganache-private-Key"
acct = web3.eth.account.privateKeyToAccount(key)
# 4. Get smart contract information
truffleFile = json.load(open('./build/contracts/greeter.json'))
abi = truffleFile['abi']
bytecode = truffleFile['bytecode']
# 5. Set contract address
contract_address = "0xD3C53651Fbd2A8a1Efe30504CC452F34e435A47F"
contract_address = Web3.toChecksumAddress(contract_address) #modify
# 6. Instantiate and deploy contract
contract = web3.eth.contract(abi=abi, bytecode=bytecode)
contract_instance = web3.eth.contract(abi=abi, address=contract_address)
greeting = "Hello all my goody people nonce"
tx = contract_instance.functions.greet(greeting).buildTransaction({'nonce': web3.eth.getTransactionCount(acct.address)})
# 7. Send transaction , and get tx receipt to get contract address
signed_tx = web3.eth.account.signTransaction(tx, key)
hash= web3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(hash.hex())
1~4.まではdeploy.pyと同じ内容ですね。
5.では、deploy.pyで出力されたコントラクトアドレスを記入します。
6.では、greetメソッドに、文字列「Hello all my goody people nonce」を設定しています。
7.で実際にトランザクションを実行し、トランザクションハッシュを取得しています。
実行がうまくいくと、以下のような出力が得られます。
True
0x4180ea5ef34994580fbd0a92eb18c216ab4c1b4a535ae8894e2acffba26c0ea5
これで、スマートコントラクトを呼び出す準備が完了しました!
スマートコントラクトの呼び出し
では最後に、スマートコントラクトの呼び出しです。
# 1. Import Module
import json
from web3 import Web3, HTTPProvider
from web3.contract import ConciseContract
# 2. Access Ganache local server
web3 = Web3(HTTPProvider("HTTP://127.0.0.1:7545"))
print(web3.isConnected())
# 4. Get smart contract information
truffleFile = json.load(open('./build/contracts/greeter.json'))
abi = truffleFile['abi']
bytecode = truffleFile['bytecode']
# 5. Set contract address
contract_address = "0xD3C53651Fbd2A8a1Efe30504CC452F34e435A47F"
contract_address = Web3.toChecksumAddress(contract_address) #modify
contract = web3.eth.contract(abi=abi, bytecode=bytecode)
# 6. Read Contract function
contract_instance = web3.eth.contract(abi=abi, address=contract_address)
print('Contract value: {}'.format(contract_instance.functions.getGreeting().call()))
これまでと違っているのは、6.の部分だけですね。6で、これまでにデプロイしたコントラクトの呼び出しを行っています。うまくいくと、文字列がプリントされるはずですね。
True
Contract value: Hello all my goody people nonce
さきほど設定した文字列が無事に出力されています!うれしい限りですね~。
おわりに
今回の記事で、実際にスマートコントラクトの準備、実装、状態変更、呼び出しまで行いました。実際には、スマートコントラクトの部分をsolidityでゴリゴリ記述しなければなりませんが、まず第一段階のHello world!的な学習としてなかなか楽しめたのではないでしょうか。
これで、「Python+Web3.pyでEthereumコントラクト学習」シリーズは終了になります。最後まで読んでいただけた方、お疲れ様でした!ありがとうございました。
また面白そうな学習トピック等あれば、引き続き記事化していきます。