javascript - 从 Node 请求整个链时误解区 block 链的 websocket 通信

标签 javascript node.js graph websocket blockchain

这是一篇很长的帖子,所以我感谢那些回答它的人。我试图理解下面区 block 链示例中的 websocket 通信。

这是区 block 链中一个 Node 的源代码:

const BrewChain = require('./brewChain');
const WebSocket = require('ws');

const BrewNode = function(port){
    let brewSockets = [];
    let brewServer;
    let _port = port
    let chain = new BrewChain();

    const REQUEST_CHAIN = "REQUEST_CHAIN";
    const REQUEST_BLOCK = "REQUEST_BLOCK";
    const BLOCK = "BLOCK";
    const CHAIN = "CHAIN";

    function init(){

        chain.init();

        brewServer = new WebSocket.Server({ port: _port });

        brewServer.on('connection', (connection) => {
            console.log('connection in');
            initConnection(connection);
        });     
    }

    const messageHandler = (connection) =>{
        connection.on('message', (data) => {
            const msg = JSON.parse(data);
            switch(msg.event){
                case REQUEST_CHAIN:
                    connection.send(JSON.stringify({ event: CHAIN, message: chain.getChain()}))    
                    break;                  
                case REQUEST_BLOCK:
                    requestLatestBlock(connection);
                    break;      
                case BLOCK:
                    processedRecievedBlock(msg.message);
                    break;  
                case CHAIN:
                    processedRecievedChain(msg.message);
                    break;  

                default:  
                    console.log('Unknown message ');
            }
        });
    }


    const processedRecievedChain = (blocks) => {
        let newChain = blocks.sort((block1, block2) => (block1.index - block2.index))

        if(newChain.length > chain.getTotalBlocks() && chain.checkNewChainIsValid(newChain)){
            chain.replaceChain(newChain);
            console.log('chain replaced');
        }
    }

    const processedRecievedBlock = (block) => {

        let currentTopBlock = chain.getLatestBlock();

        // Is the same or older?
        if(block.index <= currentTopBlock.index){
            console.log('No update needed');
            return;
        }

        //Is claiming to be the next in the chain
        if(block.previousHash == currentTopBlock.hash){
            //Attempt the top block to our chain
            chain.addToChain(block);

            console.log('New block added');
            console.log(chain.getLatestBlock());
        }else{
            // It is ahead.. we are therefore a few behind, request the whole chain
            console.log('requesting chain');
            broadcastMessage(REQUEST_CHAIN,"");
        }
    }

    const requestLatestBlock = (connection) => {
        connection.send(JSON.stringify({ event: BLOCK, message: chain.getLatestBlock()}))   
    }

    const broadcastMessage = (event, message) => {
        brewSockets.forEach(node => node.send(JSON.stringify({ event, message})))
    }

    const closeConnection = (connection) => {
        console.log('closing connection');
        brewSockets.splice(brewSockets.indexOf(connection),1);
    }

    const initConnection = (connection) => {
        console.log('init connection');

        messageHandler(connection);

        requestLatestBlock(connection);

        brewSockets.push(connection);

        connection.on('error', () => closeConnection(connection));
        connection.on('close', () => closeConnection(connection));
    }

    const createBlock = (teammember) => {
        let newBlock = chain.createBlock(teammember)
        chain.addToChain(newBlock);

        broadcastMessage(BLOCK, newBlock);

    }

    const getStats = () => {
        return {
            blocks: chain.getTotalBlocks()
        }
    }

    const addPeer = (host, port) => {
        let connection = new WebSocket(`ws://${host}:${port}`);

        connection.on('error', (error) =>{
            console.log(error);
        });

        connection.on('open', (msg) =>{
            initConnection(connection);
        });
    }

    return {
        init,
        broadcastMessage,
        addPeer,
        createBlock,
        getStats
    }

}

module.exports = BrewNode;

当 Node 使用 createBlock() 函数创建新 block 时,会使用 broadcastMessage() 函数从 Node 向所有连接的套接字广播一条消息,告诉它们新 block 已创建。连接的套接字将接收消息,并且在 messageHandler() 中它将为每个套接字命中 switch 语句中的 BLOCK 选项。我掌握了这个过程,并画了一张图来表示我的理解。

图 1

enter image description here

如前所述,当 A 创建一个新 block 时,它会将新 block 发送到它连接的 Node ,每个 Node 将验证它并可能将其添加到它的链中。此处理由 processedRecievedBlock() 函数完成。假设 B 和 C 决定将区 block 添加到他们的链中,但 D 落后了几个区 block ,因此它必须向 A 请求整个链。这就是我感到困惑的地方。我预计 D 会向 A 发送一条请求整个链的消息,如下所示:

图 2

enter image description here

但是,根据 processReceivedBlock() 函数,在这种情况下,D 将向所有连接的套接字广播 REQUEST_CHAIN 消息,当运行此行时:

broadcastMessage(REQUEST_CHAIN,"");

假设 D 连接到 E 和 F。不像图 2 中那样从 A 请求链,它似乎会向它连接的套接字发送 REQUEST_CHAIN 消息,如下所示:

图 3

enter image description here

在messageHandler()函数中,会为E和F运行switch语句中的REQUEST_CHAIN选项,他们会命中这行代码:

connection.send(JSON.stringify({ event: CHAIN, message: chain.getChain()}));

据我了解,这将导致 E 和 F 将自己的链发送回自己,如下所示:

图 4

enter image description here

我想知道当 D 需要从 A 请求整个链时为什么图 2 没有出现。跟踪代码让我相信图 3 和图 4 出现了,它们似乎都没有用。

当一个 Node 必须从另一个 Node 请求整个链时,我试图了解这段代码中到底发生了什么。我一定是误解了这些套接字在做什么。

完整源代码:https://github.com/dbjsdev/BrewChain/blob/master/brewNode.js

最佳答案

感谢您提出描述性问题。 :)

在大多数情况下,您是对的,图 3 是对该过程的该部分的正确描述。但图 4 是错误的。

请注意,对等点之间的每个套接字连接都会导致一个不同的connection实例,这些实例共同维护在brewSockets中。

因此,当 A/E/F 收到来自 D 的关于connection 的请求时,它们会响应整个链,如下面的代码所示:

connection.send(JSON.stringify({ event: CHAIN, message: chain.getChain()}));

D 然后处理 CHAIN 消息:

const processedRecievedChain = (blocks) => {
        let newChain = blocks.sort((block1, block2) => (block1.index - block2.index))

        if(newChain.length > chain.getTotalBlocks() && chain.checkNewChainIsValid(newChain)){
            chain.replaceChain(newChain);
            console.log('chain replaced');
        }
}

现在,进入“为什么”!

首先,基本原则是我们信任网络,而不仅仅是一个 Node 。因此,您想从尽可能多的来源验证链的真实性。

其次,您想要来自同行的最新链,而不仅仅是任何随机链。

通过这样做,我们确保任何 Node 都与其对等 Node 一样最新。因此,D Node 从多个来源获取链并存储最新的验证链。

希望对您有所帮助!

关于javascript - 从 Node 请求整个链时误解区 block 链的 websocket 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49185732/

相关文章:

javascript - 将 jQuery 传递给 .animate 回调

javascript - Highcharts 仪表在 IE8 中不起作用

javascript - 从 JsRender 调用 JavaScript 函数

.net - Microsoft GraphEngine LIKQ 查询

javascript - 网络图

javascript - 数组符号运算顺序

javascript - jQuery post 使用express接收数据

json - 将逗号分隔的 JSON 转换为换行符分隔的 Node

node.js - 我已经更新了github上的数据,但是 Node 模块请求仍然得到旧数据

Python相当于Matlab中的 'hold on'