graph TD
用户 --> 浏览器[简易浏览器前端]
浏览器 --> API[HTTP 调用<br/>GET /balance /block /chain /block/:idx /tx/:id]
API --> 节点[某节点 5001 端口]
节点 --> 共识[PBFT 共识确认]
节点 --> 本地链[本地区块链数据]
浏览器 --> 广播[POST /broadcast 传播新交易]
广播 --> 共识
共识 --> 节点
style 浏览器 fill:#c8e6c9
style 共识 fill:#ffe0b2
每个节点自带 JSON API——通过 GET 请求查询余额、查看区块、浏览完整链。
16.6.1 API 端点设计
text
GET /chain → 完整链(含所有交易)
GET /blocks/<index> → 单区块详情
GET /balance/<address> → 地址余额
GET /transactions/pending→ 待打包交易池
GET /nodes/resolve → 触发共识(最长链)
GET /peers → 连接的对等节点浏览器 HTML(单文件内嵌)
html
<!-- 嵌入式浏览器:直接嵌入 Flask 响应 -->
<!DOCTYPE html>
<html>
<style>
body { font-family: monospace; max-width: 800px; margin: 0 auto; padding: 20px; }
.block { border: 1px solid #ccc; padding: 10px; margin: 10px 0; background: #f9f9f9; }
.hash { color: #2196F3; word-break: break-all; }
.tx { color: #4CAF50; margin-left: 20px; }
</style>
<body>
<h1>⛏️ 迷你链浏览器</h1>
<div id="stats"></div>
<div id="chain"></div>
<script>
async function load() {
const res = await fetch('/chain');
const {chain, length} = await res.json();
document.getElementById('stats').innerHTML =
`<h3>链高度: {chain[chain.length-1].difficulty}</h3>`;
document.getElementById('chain').innerHTML = chain.map(b => `
<div class="block">
<div><b>区块 #{new Date(b.timestamp*1000).toLocaleString()}</div>
<div class="hash">🔗 ${b.hash.substring(0,30)}...</div>
<div class="hash">⬅️ ${b.previous_hash.substring(0,30)}...</div>
<div>Nonce: {b.transactions.length}</div>
${b.transactions.map(tx => `
<div class="tx">
{tx.recipient.substring(0,10)}...
金额: ${tx.amount}
</div>
`).join('')}
</div>
`).join('');
}
load();
setInterval(load, 5000); // 每 5 秒刷新
</script>
</body>
</html>16.6.2 快速测试
bash
# 查看余额
curl http://localhost:3001/balance/Alice
# → { "address": "Alice", "balance": 50.0 }
# 查看特定区块
curl http://localhost:3001/blocks/1 | jq
# 查看待打包
curl http://localhost:3001/transactions/pending, 前往 → 16.7 部署演示与端到端测试 |*
评论
0评论加载中…