始める前に、まず基本的な概念を簡単に理解しましょう。以下のいくつかの点にまとめました。Web3.0とは何か、ブロックチェーンとどのような関係があるのか? (前回の記事がここで役立ちますね)
要件:PythonベースのWeb 3.0画像アップロードシステムを開発します。このシステムは、ユーザーが画像をアップロードし、その画像を分散型ネットワークに保存し、同時にトランザクション情報をブロックチェーンに記録することを可能にします。もともとは遊びで書いていたもので、ユーザー認証やファイル操作を統合した完全な管理システムにして、「画像アップロードサービスの最終的な解決策」にしようと考えたこともありましたが、実際にやってみるとあまり現実的ではないことに気づき、断念しました。しかし、私は昔から画像にこだわりがあるのです。
ステップの概要
- 環境設定:Pythonを使用して開発し、必要なPythonライブラリをインストールします。
- IPFS統合:画像をIPFSにアップロードし、画像のCID(Content Identifier)を取得します。
- ブロックチェーン統合:IPFSのCIDをブロックチェーンに記録します。
- Webインターフェース:Flaskを使用して、ユーザーが画像をアップロードできるWebインターフェースを作成します。
詳細なステップ
1. 環境設定
必要なPythonライブラリをインストールします:
pip install flask web3 ipfshttpclient
2. IPFS統合
IPFS(InterPlanetary File System)は、ピアツーピアのファイルストレージプロトコルです。ipfshttpclientライブラリを使用してIPFSネットワークと対話できます。
まず、IPFSノードをインストールして実行していることを確認してください。まだIPFSをインストールしていない場合は、IPFS公式サイト でインストールガイドを見つけることができます。
以下は、画像をIPFSにアップロードするコード例です:
import ipfshttpclient
def upload_to_ipfs(file_path):
client = ipfshttpclient.connect('/ip4/127.0.0.1/tcp/5001')
res = client.add(file_path)
return res['Hash']
3. ブロックチェーン統合
web3.pyライブラリを使用してIPFSのCIDをブロックチェーンに記録します。ここではイーサリアム(Ethereum)をサンプルブロックチェーンとして使用します。
以下は、IPFSのCIDを保存するための簡単なスマートコントラクトの例です:
pragma solidity ^0.8.0;
contract IPFSStorage {
mapping(address => string[]) public userCIDs;
function storeCID(string memory cid) public {
userCIDs[msg.sender].push(cid);
}
function getCIDs() public view returns (string[] memory) {
return userCIDs[msg.sender];
}
}
このコントラクトをコンパイルしてデプロイした後、以下のPythonコードを使用してスマートコントラクトと対話します:
from web3 import Web3
# イーサリアムノードに接続
w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))
# コントラクトアドレスとABI(コントラクトデプロイ後に取得)
contract_address = 'YOUR_CONTRACT_ADDRESS'
contract_abi = 'YOUR_CONTRACT_ABI'
contract = w3.eth.contract(address=contract_address, abi=contract_abi)
def store_cid_on_blockchain(cid, account, private_key):
txn = contract.functions.storeCID(cid).buildTransaction({
'from': account,
'nonce': w3.eth.getTransactionCount(account),
'gas': 2000000,
'gasPrice': w3.toWei('50', 'gwei')
})
signed_txn = w3.eth.account.sign_transaction(txn, private_key=private_key)
txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
return txn_hash.hex()
4. Webインターフェース
Flaskを使用して画像をアップロードするためのWebインターフェースを作成します。
from flask import Flask, request, jsonify
import os
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return jsonify({'error': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No selected file'})
if file:
file_path = os.path.join('/path/to/save/uploads', file.filename)
file.save(file_path)
# IPFSにアップロード
cid = upload_to_ipfs(file_path)
# ブロックチェーンに保存
account = 'YOUR_ETHEREUM_ACCOUNT'
private_key = 'YOUR_PRIVATE_KEY'
txn_hash = store_cid_on_blockchain(cid, account, private_key)
return jsonify({'cid': cid, 'transaction_hash': txn_hash})
if __name__ == '__main__':
app.run(debug=True)
アップロードが成功すると、HASH値が返されます。これがIPFS上での画像のIDです。 ローカルゲートウェイからのアクセス:ipfs://QmVJGX3FJPZsAgGMtJZoTt14XBj8QKhPwaaP4UfCcvYaN2 、ipfs://QmRF9mejyfq89vAJ5yfsBbmVY3RUcLqfSsVTAmAbS8U2xD 外部ゲートウェイ:https://ipfs.crossbell.io/ipfs/QmVJGX3FJPZsAgGMtJZoTt14XBj8QKhPwaaP4UfCcvYaN2 、https://ipfs.crossbell.io/ipfs/QmRF9mejyfq89vAJ5yfsBbmVY3RUcLqfSsVTAmAbS8U2xD
スマートコントラクト
Solidityを使用してスマートコントラクトを作成し、solcコンパイラでコントラクトをコンパイルし、web3.pyライブラリを使用してイーサリアムネットワークにコントラクトをデプロイします。
1. スマートコントラクトのコードを記述する
まず、Solidityファイル(例:IPFSStorage.sol)を作成し、スマートコントラクトのコードを記述します:
// IPFSStorage.sol
pragma solidity ^0.8.0;
contract IPFSStorage {
mapping(address => string[]) public userCIDs;
function storeCID(string memory cid) public {
userCIDs[msg.sender].push(cid);
}
function getCIDs() public view returns (string[] memory) {
return userCIDs[msg.sender];
}
}
2. スマートコントラクトをコンパイルする
Solidityスマートコントラクトをコンパイルするには、solcコンパイラを使用します。以下のコマンドでSolidityコンパイラをインストールできます:
npm install -g solc
次に、以下のコマンドでスマートコントラクトをコンパイルします:
solc --abi --bin IPFSStorage.sol -o build/
これにより、IPFSStorage.abi(コントラクトのABI)とIPFSStorage.bin(コントラクトのバイトコード)の2つのファイルが生成されます。
3. スマートコントラクトをデプロイする
web3.pyライブラリを使用してコントラクトをデプロイします。イーサリアムノード(例:ローカル開発環境のGanache
)が実行されていることを確認してください。
まず、web3.pyをインストールします:
pip install web3
次に、以下のPythonスクリプトを作成して実行し、コントラクトをデプロイします:
from web3 import Web3
# イーサリアムノードに接続(Ganacheローカルノードを例として使用)
w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:7545'))
# コントラクトのABIとバイトコードを読み込む
with open('build/IPFSStorage.abi', 'r') as abi_file:
contract_abi = abi_file.read()
with open('build/IPFSStorage.bin', 'r') as bin_file:
contract_bytecode = bin_file.read()
# デプロイ用のアカウントと秘密鍵を設定(Ganacheが提供するアカウントを使用)
deployer_account = '0xYourAccountAddress'
private_key = 'YourPrivateKey'
# コントラクトオブジェクトを作成
IPFSStorage = w3.eth.contract(abi=contract_abi, bytecode=contract_bytecode)
# トランザクションを構築
transaction = IPFSStorage.constructor().buildTransaction({
'from': deployer_account,
'nonce': w3.eth.getTransactionCount(deployer_account),
'gas': 2000000,
'gasPrice': w3.toWei('50', 'gwei')
})
# トランザクションに署名
signed_txn = w3.eth.account.sign_transaction(transaction, private_key=private_key)
# トランザクションを送信し、トランザクションハッシュを取得
txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
print(f'Transaction hash: {txn_hash.hex()}')
# トランザクションの確認を待つ
txn_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
print(f'Contract deployed at address: {txn_receipt.contractAddress}')
まとめ
スマートコントラクトをコンパイルして生成されたABIとバイトコードは、コントラクトとの対話に使用されます。コントラクトのデプロイには、トランザクションの作成、署名、そしてイーサリアムネットワークへの送信が含まれます。デプロイが成功すると、トランザクションレシートからコントラクトアドレスを取得し、そのアドレスを使用してコントラクトと対話できます。