iT邦幫忙

0

實作輕量級區塊鏈 (三):交易池與 P2P 網路廣播機制初步

  • 分享至 

  • xImage
  •  

我們成功實作了工作量證明(PoW),讓區塊的產生有了合理的節奏。但在前幾天的程式碼中,我們的區塊裡都只放了一筆簡單的 data(例如一個溫濕度數值)。

在真實的分散式網路中,資料產生的速度遠比「挖出一個區塊」的速度快太多了。當數十個感測器同時回傳資料時,這些資料不可能瞬間就被寫入區塊鏈中。它們需要一個「候機室」來排隊,等待節點(礦工)把它們打包上鏈。這個候機室,我們稱之為未確認交易池 (Pending Transactions 或 Mempool)。今天,我們就要來實作這個機制,並初步探討節點間如何透過 P2P 網路廣播這些資訊。

定義交易 (Transaction) 類別
首先,我們需要將原本單純的字串 data,升級成一個結構化的「交易」。在物聯網的場景中,一筆交易代表的可能是一個感測節點向主控端回傳的加密數據。
'''
class Transaction {
constructor(fromAddress, toAddress, data) {
this.fromAddress = fromAddress; // 發送方 (例如:感測器 MAC 地址或公鑰)
this.toAddress = toAddress; // 接收方 (例如:資料收集中心)
this.data = data; // 實際的感測數據或酬載
}
}
'''

升級區塊鏈:加入交易池與挖礦獎勵
接著,我們回到 Blockchain 類別。我們要新增一個陣列來存放那些「還沒被打包的交易」,並且修改挖礦的邏輯,讓礦工在挖礦時,能順便把交易池裡面的資料全部打包進去。
'''
class Blockchain {
constructor() {
this.chain = [this.createGenesisBlock()];
this.difficulty = 4;
this.pendingTransactions = []; // 新增:未確認交易池
this.miningReward = 10; // 新增:給礦工的獎勵(如果是純 IoT 應用可省略,但此處保留 Web3 特性)
}

// ... (保留 createGenesisBlock, getLatestBlock 等方法)

// 新增:將新交易推入交易池中排隊
createTransaction(transaction) {
    this.pendingTransactions.push(transaction);
}

// 修改:將原本的 addBlock 替換成 minePendingTransactions
minePendingTransactions(miningRewardAddress) {
    // 在真實世界中,區塊容量有限,礦工會挑選手續費高的交易。
    // 為了簡化,我們這裡一次把所有 pendingTransactions 全包進去。
    let block = new Block(
        this.chain.length,
        Date.now().toString(),
        this.pendingTransactions // 把候機室裡的交易塞進區塊
    );

    block.mineBlock(this.difficulty);
    console.log("區塊開採成功!");
    this.chain.push(block);

    // 區塊上鏈後,清空交易池,並放入一筆給礦工的獎勵交易(等待下一個區塊打包)
    this.pendingTransactions = [
        new Transaction(null, miningRewardAddress, "系統發放挖礦獎勵")
    ];
}

}
'''

測試交易池機制
現在我們的架構更貼近真實的以太坊或比特幣了。讓我們來模擬多個感測器回傳資料的情境:
'''let myIoTChain = new Blockchain();

// 1. 感測器開始回傳資料(這些資料會進入交易池排隊)
myIoTChain.createTransaction(new Transaction("Sensor_A", "Gateway", { temp: 24 }));
myIoTChain.createTransaction(new Transaction("Sensor_B", "Gateway", { temp: 25 }));

// 2. 礦工節點啟動挖礦,把交易池裡的資料打包上鏈
console.log("\n礦工節點開始挖礦...");
myIoTChain.minePendingTransactions("Miner_Node_01");

// 3. 檢查區塊鏈內容
console.log("\n目前的區塊鏈狀態:");
console.log(JSON.stringify(myIoTChain.chain, null, 4));
'''

執行後你會發現,Sensor_A 與 Sensor_B 的資料被一起安穩地封裝在區塊索引 1 裡面了!

P2P 網路與狀態同步的初步探討
到目前為止,我們所有的程式碼都跑在單一的 Node.js 行程中。但在真實世界裡,區塊鏈是由散佈在各地的節點所組成的。當 Sensor_A 產生一筆交易時,它必須透過 P2P (Peer-to-Peer) 網路,例如使用 WebSockets,將這筆交易廣播給所有節點。

這不僅僅是理論。當我們真正要把這個輕量級區塊鏈推向實務環境,甚至作為未來研究所推甄或專題評審的亮點時,這些節點通常會被打包成 Docker 容器,並透過 Kubernetes 進行叢集管理。而在相對封閉的邊緣感測器網路中,節點間的狀態同步甚至可以借鑒 Raft 這類分散式共識演算法的日誌複製精神來輔助廣播機制,確保每個閘道器(Gateway)的 Mempool 狀態保持高度一致,讓底層架構更加穩健。

今天我們補齊了區塊鏈在資料流動上最重要的一環:交易池。
經過這幾天的實作,我們已經擁有了一個五臟俱全的輕量級區塊鏈底層。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言