開始前,我們先簡單瞭解一下基本的概念,我大致歸納為以下幾個點
什麼是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
(合約的位元組碼)。
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和位元組碼用於與合約互動,部署合約則涉及到建立交易、簽署交易並將交易傳送到以太坊網路。部署成功後,可以透過交易回執獲取合約地址,並使用這個地址與合約進行互動。