在開始之前,我們先簡單了解一下基本的概念,我大致歸納為以下幾個點 什麼是Web3.0,和區塊鏈又有什麼關係?(上回的文章不就派上用場了)
需求:開發一個基於Python的Web 3.0圖片上傳系統。這個系統將允許用戶上傳圖片,並將圖片儲存在去中心化的網路上,同時記錄交易資訊在區塊鏈上。 本來只是寫著玩的,想過要寫成用戶認證、檔案操作集成全套管理的,讓他「終將成為圖片上傳服務的最終解決方案」。實際下來卻發現不是很實際,就作罷了,奈何我一直以來對圖片這麼執著。
步驟概述
- 環境設定:使用Python開發,安裝必要的Python函式庫。
 - IPFS整合:將圖片上傳到IPFS,取得圖片的CID(內容識別碼)。
 - 區塊鏈整合:將IPFS CID記錄在區塊鏈上。
 - Web介面:使用Flask建立一個Web介面,允許用戶上傳圖片。
 
詳細步驟
1. 環境設定
安裝所需的Python函式庫:
pip install flask web3 ipfshttpclient
2. IPFS整合
IPFS(星際檔案系統)是一種點對點的檔案儲存協定。我們可以使用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和位元碼用於與合約互動,部署合約則涉及到建立交易、簽署交易並將交易發送到以太坊網路。部署成功後,可以透過交易收據取得合約地址,並使用這個地址與合約進行互動。