Python+区块链实战:Web3.py开发智能合约与去中心化投票系统
今天咱们用Python搞点有意思的——用库开发一个真正的区块链应用。想象一下,你正在创建一个不会被篡改的投票系统,每个投票记录都永久保存在区块链上,这可比传统数据库酷多了!
今天咱们用Python搞点有意思的——用Web3.py库开发一个真正的区块链应用。想象一下,你正在创建一个不会被篡改的投票系统,每个投票记录都永久保存在区块链上,这可比传统数据库酷多了!
先准备好工具箱
安装必要的库:
pip install web3 solcx python-dotenv
solcx是Solidity编译器,python-dotenv用来读取私钥等敏感信息。记得在项目根目录创建.env文件保存你的钱包私钥:
PRIVATE_KEY=你的钱包私钥
INFURA_URL=你的Infura节点URL
温馨提示:千万别把私钥直接写在代码里!新手常犯这个低级错误,分分钟钱包被掏空。
写个智能合约试试手
新建Vote.sol文件,用Solidity语言写投票合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Voting {
mapping(address => bool) public hasVoted;
mapping(string => uint) public votesCount;
string[] public candidates;
constructor(string[] memory _candidates) {
candidates = _candidates;
}
function vote(string memory candidate) public {
require(!hasVoted[msg.sender], "Already voted");
require(isValidCandidate(candidate), "Invalid candidate");
hasVoted[msg.sender] = true;
votesCount[candidate] += 1;
}
function isValidCandidate(string memory candidate) private view returns(bool) {
for(uint i=0; i<candidates.length; i++) {
if(keccak256(bytes(candidates[i])) == keccak256(bytes(candidate))) {
return true;
}
}
return false;
}
}
这合约做了三件事:初始化候选人列表、防止重复投票、验证候选人有效性。区块链上的代码就像永不休息的公证人,忠实地执行这些规则。
用Python和合约对话
部署合约的Python脚本:
from web3 import Web3
from solcx import compile_standard, install_solc
import json
import os
from dotenv import load_dotenv
load_dotenv()
install_solc('0.8.0')
# 编译合约
with open("Vote.sol", "r") as f:
contract_source = f.read()
compiled_sol = compile_standard({
"language": "Solidity",
"sources": {"Vote.sol": {"content": contract_source}},
"settings": {"outputSelection": {"*": {"*": ["abi", "evm.bytecode"]}}}
})
# 连接区块链
w3 = Web3(Web3.HTTPProvider(os.getenv("INFURA_URL")))
account = w3.eth.account.from_key(os.getenv("PRIVATE_KEY"))
# 部署合约
contract = w3.eth.contract(
abi=compiled_sol['contracts']['Vote.sol']['Voting']['abi'],
bytecode=compiled_sol['contracts']['Vote.sol']['Voting']['evm']['bytecode']['object']
)
tx = contract.constructor(["Alice", "Bob"]).build_transaction({
'from': account.address,
'nonce': w3.eth.get_transaction_count(account.address),
'gas': 1728712,
'gasPrice': w3.to_wei('21', 'gwei')
})
signed_tx = account.sign_transaction(tx)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"合约地址: {tx_receipt.contractAddress}")
运行后你会得到一个类似0x5B3...的合约地址,这就是你的投票系统在区块链上的身份证号码。
投票功能实现
和合约交互的Python代码:
# 初始化已部署的合约
contract_address = "你的合约地址"
contract = w3.eth.contract(
address=contract_address,
abi=compiled_sol['contracts']['Vote.sol']['Voting']['abi']
)
# 执行投票
def cast_vote(candidate):
tx = contract.functions.vote(candidate).build_transaction({
'from': account.address,
'nonce': w3.eth.get_transaction_count(account.address)
})
signed_tx = account.sign_transaction(tx)
return w3.eth.send_raw_transaction(signed_tx.rawTransaction)
# 查询票数
def get_votes(candidate):
return contract.functions.votesCount(candidate).call()
# 测试投票
cast_vote("Alice")
print(f"Alice得票数: {get_votes('Alice')}") # 输出1
试试给不存在的候选人投票,你会看到合约像严厉的监考老师一样抛出错误——这就是智能合约的可靠性。
搞个简单的前端
用Flask做个可视化界面(完整版需要处理会话和错误):
from flask import Flask, request
app = Flask(__name__)
@app.route('/vote', methods=['POST'])
def handle_vote():
candidate = request.form['candidate']
try:
cast_vote(candidate)
return f"成功投给{candidate}!"
except Exception as e:
return str(e), 400
@app.route('/results')
def show_results():
return {
"Alice": get_votes("Alice"),
"Bob": get_votes("Bob")
}
if __name__ == '__main__':
app.run(port=3000)
现在访问http://localhost:3000/results就能看到实时票数,区块链的数据就像公开的玻璃柜,谁都能查看但无法篡改。
这些坑你别踩
-
• Gas费用估算:用
estimate_gas()方法提前计算交易成本,别让用户因为Gas费不足投票失败 -
• 事件监听:合约里可以添加
Voted事件,用Web3.py的过滤器实时捕获新投票 -
• 测试网络:先用Rinkeby或Goerli测试网练手,别在主网上烧真金白银
-
• 错误处理:捕获
ContractLogicError等异常,给用户友好提示而不是满屏红色错误
现在你手里已经握着进入Web3世界的钥匙了。区块链不是魔法,本质就是代码+密码学+分布式系统,多动手部署几个合约,很快就能找到感觉。下次咱们可以试试给投票系统加上代币激励,让参与者获得投票积分——那才是真正的区块链玩法!
更多推荐




所有评论(0)