200行 JS 代碼實現區塊鏈

AleHipple 6年前發布 | 49K 次閱讀 區塊鏈 JavaScript開發

200行 JS 代碼實現區塊鏈

原文 A blockchain in 200 lines of code

譯者:若愚,來自饑人谷, 更多好文,關注“饑人谷”公眾號

區塊鏈的基本概念非常簡單:一個分布式數據庫維持不斷增長的有序記錄列表。然而當我們談論區塊鏈時,我們也會談論我們用區塊鏈所要解決的問題,這二者通常很容易弄混淆。流行的基于區塊鏈的項目如比特幣和以太坊就是這種情況 。術語“區塊鏈”通常與交易、智能合約 或加密貨幣等概念緊密相關。

這使得理解區塊鏈是一項必然要艱巨的任務。特別是源碼級別的理解。在這里,我將介紹一個使用200行代碼實現的超級簡單的區塊鏈—— NaiveChain

 

塊結構

第一個邏輯步驟是確定塊結構。為了讓事情盡可能簡單,我們只包含最必要的:索引(index),時間戳(timestamp),數據(data),哈希(hash)和上一個哈希(previousHash)。

 

200行 JS 代碼實現區塊鏈

 

class Block {
    constructor(index, previousHash, timestamp, data, hash) {
        this.index = index;
        this.previousHash = previousHash.toString();
        this.timestamp = timestamp;
        this.data = data;
        this.hash = hash.toString();
    }
}

塊哈希

該塊需要被哈希運算以保持數據的完整性。SHA-256被用來做哈希算法處理塊的內容。需要注意的是這個哈希與“挖礦” 無關,因為沒有解決工作量證明(Proof Of Work )的問題。

var calculateHash = (index, previousHash, timestamp, data) => {
    return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();
};

創建塊

要創建一個塊,我們必須知道上一個塊的哈希,并創建剩余的所需內容(=索引,哈希,數據和時間戳)。塊數據是由終端用戶提供。

var generateNextBlock = (blockData) => {
    var previousBlock = getLatestBlock();
    var nextIndex = previousBlock.index + 1;
    var nextTimestamp = new Date().getTime() / 1000;
    var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData);
    return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);
};

存儲塊

內存中的Javascript數組用于存儲區塊鏈。區塊鏈的第一個區塊也叫“創世紀塊(譯者著:genesis-block,區塊鏈中的第一個塊)”,它是直接寫死的。

var getGenesisBlock = () => {
    return new Block(0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");
};

var blockchain = [getGenesisBlock()];

驗證塊的完整性

在任何時候,我們必須能夠驗證塊或區塊鏈的完整性。特別是當我們從其他節點接收到新塊時,并且必須決定是否接受它們。

var isValidNewBlock = (newBlock, previousBlock) => {
    if (previousBlock.index + 1 !== newBlock.index) {
        console.log('invalid index');
        return false;
    } else if (previousBlock.hash !== newBlock.previousHash) {
        console.log('invalid previoushash');
        return false;
    } else if (calculateHashForBlock(newBlock) !== newBlock.hash) {
        console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash);
        return false;
    }
    return true;
};

選擇最長的鏈

任意時間,鏈中應始終只有一組塊。如果發生沖突(例如下圖中兩個節點都生成id 為72的塊),我們選擇具有最長塊數的鏈。

 

200行 JS 代碼實現區塊鏈

 

var replaceChain = (newBlocks) => {
    if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) {
        console.log('Received blockchain is valid. Replacing current blockchain with received blockchain');
        blockchain = newBlocks;
        broadcast(responseLatestMsg());
    } else {
        console.log('Received blockchain invalid');
    }
};

與其他節點通信

一個節點的最重要的職能是與其他節點共享和同步區塊鏈。以下規則用來保持網絡同步。

  • 當一個節點產生一個新塊時,它將它廣播到網絡
  • 當一個節點連接到一個新的節點時,它將查詢最新的塊
  • 當一個節點遇到一個索引大于當前已知塊的塊時,它會將該塊添加到當前鏈中,或者查詢完整的區塊鏈。

 

200行 JS 代碼實現區塊鏈

 

我們暫未實現節點自動發現,必須手動添加對等點的位置(=URLs)。

控制節點

用戶必須能夠以某種方式控制節點。這是通過設置HTTP服務器完成的。

var initHttpServer = () => {
    var app = express();
    app.use(bodyParser.json());

    app.get('/blocks', (req, res) => res.send(JSON.stringify(blockchain)));
    app.post('/mineBlock', (req, res) => {
        var newBlock = generateNextBlock(req.body.data);
        addBlock(newBlock);
        broadcast(responseLatestMsg());
        console.log('block added: ' + JSON.stringify(newBlock));
        res.send();
    });
    app.get('/peers', (req, res) => {
        res.send(sockets.map(s => s._socket.remoteAddress + ':' + s._socket.remotePort));
    });
    app.post('/addPeer', (req, res) => {
        connectToPeers([req.body.peer]);
        res.send();
    });
    app.listen(http_port, () => console.log('Listening http on port: ' + http_port));
};

如上所示,用戶能夠通過以下方式與節點交互:

  • 列出所有的塊
  • 用用戶給出的內容創建一個新塊
  • 列出或添加節點

控制節點最直接的方法是使用Curl:

#get all blocks from the node
curl http://localhost:3001/blocks

架構

值得注意的是,一個節點實際上暴露了兩個Web服務器:一個用于控制節點(HTTP服務器),一個用于節點之間的點對點通信(Websocket HTTP服務器)。

 

200行 JS 代碼實現區塊鏈

 

結論

NaiveChain是為演示和學習目的而創建的。因為它不具有“挖礦”算法(PoS 或者PoW),不能在公共網絡中使用。盡管如此,它仍然實現了功能區塊鏈的基本功能。

 

來自: https://zhuanlan.zhihu.com/p/34827027

 本文由用戶 AleHipple 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!