Python+Web3.pyでEthereumコントラクト学習 (その3)

Python

はじめに

Python + Web3.pyでEthereumを学習する記事、その3です。

その2では、「Ethereumの送金」を実施しました。その3では、「スマートコントラクト関数のデプロイ(実装)と呼び出し」を行っていきます!

事前準備

Node.jsのインストール

さて、今回は「Truffle」とよばれるイーサリアム開発用のフレームワークを使います。Truffleを使うためには、Node.jsというJavaScript実行環境をまずインストールすることになります。以下のサイトより、ご利用のOSのLTS推奨版をインストールしましょう。

ダウンロード | Node.js
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

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コントラクト学習」シリーズは終了になります。最後まで読んでいただけた方、お疲れ様でした!ありがとうございました。

また面白そうな学習トピック等あれば、引き続き記事化していきます。

タイトルとURLをコピーしました