基於Web3.0的區塊鏈圖片上傳

阿珏酱發表於2024-06-17

開始前,我們先簡單瞭解一下基本的概念,我大致歸納為以下幾個點
什麼是Web3.0,和區塊鏈又有什麼關係?(上回的文章不就派上用場了)

需求:開發一個基於Python的Web 3.0圖片上傳系統。這個系統將允許使用者上傳圖片,並將圖片儲存在去中心化的網路上,同時記錄交易資訊在區塊鏈上。
本就是寫著玩的,想過要寫成使用者認證檔案操作整合全套管理的,讓他‘終將成為圖片上傳服務的最終解決方案’
實際下來卻發現不是很實際,就作罷了,奈何我一直以來對圖片這麼執著

步驟概述

  1. 環境設定:使用Python開發,安裝必要的Python庫。
  2. IPFS整合:將圖片上傳到IPFS,獲取圖片的CID(Content Identifier)。
  3. 區塊鏈整合:將IPFS CID記錄在區塊鏈上。
  4. 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/QmVJGX3FJPZsAgGMtJZoTt14XBj8QKhPwaaP4UfCcvYaN2https://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和位元組碼用於與合約互動,部署合約則涉及到建立交易、簽署交易並將交易傳送到以太坊網路。部署成功後,可以透過交易回執獲取合約地址,並使用這個地址與合約進行互動。

相關文章