JS 实现区块链分布式网络

这篇具有很好参考价值的文章主要介绍了JS 实现区块链分布式网络。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JS 实现区块链网络

这里主要 JS 实现区块链 实现的部分继续下去,对 Blockchain 这个对象有一些修改,如果使用 TS 的话可能要修改对应的 interface,但是如果是 JS 的话就无所谓了。

需要安装的依赖有:

  • express

  • body-parser

    现在的 express 已经不内置 body-parser,需要作为单独的依赖下载

  • request

    不下载会报错,是使用 request-promise 所需要的依赖

  • request-promise

可选的依赖包包括:

  • concurrently
  • nodemon

这两个主要为了方便热更新,详情参考:TypeScript 服务端热更新

⚠️:request 和 request-promise 已经 deprecated 了,具体 reference 可以参考 Request’s Past, Present and Future,以及 request 的代替品可以在这里查看:Alternative libraries to request

实现网络

单独的一个节点所要提供的功能有:

  • 返回当前的 blockchain
  • 添加新的交易
  • 挖矿

package.json 的配置就不多提了,我是 yarn+concurrently+nodemon 的搭配。

基础设定如下:

  • index.ts

    import express from 'express';
    import bodyParser from 'body-parser';
    
    const bitcoin = new Blockchain();
    
    const app = express();
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    
    app.listen(3331, () => {
      console.log(`Listening on port 3331...`);
    });
    

这个时候服务器就起来了,是时候实现对应的 API 功能了。

get blockchain

第一个 API 的实现特别简单,只需要返回当前的 blockchain 即可:

app.get('/blockchain', (req, res) => {
  res.send(bitcoin);
});

post transaction

这里是创建 transaction 的 API,基础的业务逻辑是从 request body 中获取交易的数额和交易双方的信息,随后创建一个新的 transaction,实现方法如下:

app.post('/transaction', (req, res) => {
  const { amount, sender, recipient } = req.body;

  const blockIdx: number = bitcoin.createNewTransaction(
    amount,
    sender,
    recipient
  );

  res.json({ message: `transaction will be added in block ${blockIdx}` });
});

测试结果如下:

JS 实现区块链分布式网络

JS 实现区块链分布式网络

JS 实现区块链分布式网络

JS 实现区块链分布式网络

⚠️:重复一下,在当前 block 没有被 mine 之前,所有的 transaction 都会被推到当前 block 中。

get mine

这是整个单节点上业务逻辑最复杂的一部分,同样也需要修改一下 blockchain 的实现(如果用的是 ts)。

要成功的挖出当前的 block,基础的业务逻辑如下:

  1. 获取整个 blockchain 上最后一个 block
  2. mine 这个 block,一直获取到正确的 nonce
  3. 创建一个新的交易去奖励当前的矿工
  4. 创建一个新的 block

当然,这里所需的功能在 blockchain 对象中已经实现了。

接下来就根据上面的步骤实现挖矿的功能:

// 我没有用 uuid,而是直接使用内置的 crypto 去实现生成随机的 uuid 的功能
import crypto from 'crypto';

const nodeAddress = crypto.randomUUID().split('-').join('');

app.get('/mine', (req, res) => {
  // 1. 获取当前 blockchain 上最后的 block
  const lastBlock = bitcoin.getLastBlock();
  // 2. 开始 mine,一直到获取正确的 nonce
  //    2.1 在 mine 之前也需要获取对应的数据
  const prevBlockHash = lastBlock.hash;
  //    这里是更新的地方,之前的 blockData 的数据结构 为 Transaction | Transaction[],这里更新一下
  const currBlockData = {
    transactions: bitcoin.pendingTransactions,
    index: lastBlock.index + 1,
  };
  const nonce = bitcoin.proofOfWork(prevBlockHash, currBlockData);
  const blockHash = bitcoin.hashBlock(prevBlockHash, currBlockData, nonce);

  // 3. 创建新的 transaction 去奖励当前的矿工
  //    这里的收件方为当前 network 地址(随机生成)
  bitcoin.createNewTransaction(12.5, '00', nodeAddress);

  // 4. 创建新的 block
  const newBlock = bitcoin.createNewBlock(nonce, prevBlockHash, blockHash);

  res.json({ message: 'New block mined successfully', block: newBlock });
});

blockchain 修改的部分为:

interface BlockData {
  index: number;
  transactions: Transaction[];
}

// 修改 currBlockData 的数据类型就好,其他地方不用变
class Blockchain {
  hashBlock = (
    prevBlockHash: string,
    currBlockData: BlockData,
    nonce: number
  ) => {
    // ...
  };

  proofOfWork = (prevBlockHash: string, currBlockData: BlockData) => {
    // ...
  };
}

这样就实现完了,沿用上面的结果,测试如下:

JS 实现区块链分布式网络

JS 实现区块链分布式网络

JS 实现区块链分布式网络

JS 实现区块链分布式网络

⚠️:每次 mine 都至少会创建 1 个 transaction,就是奖励当前挖矿人的奖励

实现去中心化区块链网络

区块链的一个特点就在于每一个结点都可以成为一个中心,所以每个结点都能够访问其他的结点:

JS 实现区块链分布式网络

捋一下要做到这一点的流程:

  1. 每一个结点都需要群组去保存所有链接的结点

  2. 当一个新的结点 A 加入这个家庭的时候,它要通知其他的结点,将结点 A 加到其他结点已经存在的群组中

  3. 当其他的结点成功注册了结点 A,将 A 加到了自己的通讯录中

  4. 结点 A 也需要将其他的结点加到自己的通讯录中

接下来就根据这个逻辑去实现去中心化网络

修改配置和数据结构

首先修改 blockchain 对象,当前 blockchain 应该获取当前的网络,并能够存储相关联的网络,修改如下:

const currentNodeUrl = process.argv[3];

class Blockchain {
  // ...
  currentNodeUrl: string;
  networkNodes: string[];

  constructor() {
    this.chain = [];
    this.pendingTransactions = [];
    // arbitrary values
    this.createNewBlock(100, '0', '0');

    this.currentNodeUrl = currentNodeUrl;
    this.networkNodes = [];
  }
}

这里将会使用 process.argv[3] 直接获取当前 node 的 url,因此,下一步就是修改配置文件,将 node url 作为命令行参数:

{
  "scripts": {
    "node_1": "concurrently \"tsc -w\" \"nodemon dist/index.js 3331 http://localhost:3331\"",
    "node_2": "concurrently \"tsc -w\" \"nodemon dist/index.js 3332 http://localhost:3332\"",
    "node_3": "concurrently \"tsc -w\" \"nodemon dist/index.js 3333 http://localhost:3333\"",
    "node_4": "concurrently \"tsc -w\" \"nodemon dist/index.js 3334 http://localhost:3334\"",
    "node_5": "concurrently \"tsc -w\" \"nodemon dist/index.js 3335 http://localhost:3335\""
  }
}

again,这里用了 ts+nodemon+concurrently,所以这么修改的,如果不用一样的配置,可能需要自己想办法修改一下参数的问题。

运行结果如下:

JS 实现区块链分布式网络

这样当前网络上就有 5 个不相关联的结点正在运行了。

post register node

这一步其实是实现的步骤 3,也就是其他结点接受一个参数,并且将结点 A 加到自己的通讯录中。对于当前结点来说,它只需要知道 A 的地址,并且判断:

  1. 这个我是不是 A
  2. 我是不是已经加过 A 了

如果二者都不满足,那么当前结点就将 A 加入通讯录中。

app.post('/register-node', (req, res) => {
  const newNodeUrl = req.body.newNodeUrl,
    // 我没加过 A
    nodeNotAlreadyPresent = !bitcoin.networkNodes.includes(newNodeUrl),
    // 我不是 A
    notCurrentNode = bitcoin.currentNodeUrl !== newNodeUrl;

  if (nodeNotAlreadyPresent && notCurrentNode)
    bitcoin.networkNodes.push(newNodeUrl);

  // 这个也可以加到 if 里面,else 里面的信息表示没有已经存在或是自己
  res.json({ message: 'New node registered successfully.' });
});

JS 实现区块链分布式网络

JS 实现区块链分布式网络

这里 3331 收到了 3333,所以 3331 会将 3333 加到自己的通讯录中,而 3333 暂时还没有将 3331 加到自己的通讯录中。

post register nodes bulk

这一步是滴 4 步,即其他的结点已经将 A 加到通讯录中了,A 也要将其他的结点加到通讯录中,所以这里接受的参数是一个数组。

实现如下:

app.post('/register-nodes-bulk', (req, res) => {
  const allNetworkNodes: string[] = req.body.allNetworkNodes;
  allNetworkNodes.forEach((networkNodeUrl) => {
    const nodeNotAlreadyPresent =
        !bitcoin.networkNodes.includes(networkNodeUrl),
      notCurrentNode = bitcoin.currentNodeUrl !== networkNodeUrl;

    if (nodeNotAlreadyPresent && notCurrentNode)
      bitcoin.networkNodes.push(networkNodeUrl);
  });
  res.json({ message: 'Bult registration successful.' });
});

测试如下:

JS 实现区块链分布式网络

JS 实现区块链分布式网络

这两个细节都完成了,现在可以跳回去补全第 2 步了。

post register & broadcast

实现如下:

app.post('/register-and-broadcast-node', (req, res) => {
  const newNodeUrl = req.body.newNodeUrl;
  if (!bitcoin.networkNodes.includes(newNodeUrl))
    bitcoin.networkNodes.push(newNodeUrl);

  const regNodesPromises: RequestPromise<any>[] = [];

  bitcoin.networkNodes.forEach((networkNodeUrl) => {
    // register node
    const requestOptions = {
      uri: networkNodeUrl + '/register-node',
      method: 'POST',
      body: { newNodeUrl },
      json: true,
    };

    regNodesPromises.push(rp(requestOptions));
  });

  Promise.all(regNodesPromises)
    .then((data) => {
      const bulkRegisterOptions = {
        uri: newNodeUrl + '/register-nodes-bulk',
        method: 'POST',
        body: {
          allNetworkNodes: [...bitcoin.networkNodes, bitcoin.currentNodeUrl],
        },
        json: true,
      };

      return rp(bulkRegisterOptions);
    })
    .then((data) => {
      res.json({ message: 'New node registered with network successfully.' });
    });
});

测试结果如下:

JS 实现区块链分布式网络

这里 3331 和 3332 作为两个单独的结点被连接在了一起了,从逻辑上可以理解声 3332 加入到了 3331 的群组中。

JS 实现区块链分布式网络

3331 所在群组通过判断,发现 3332 不在自己的群组中,所以它们决定把 3332 加到各自成员中的通讯录中(即所有群组成员都调用一次 /register-node)。

JS 实现区块链分布式网络

成功哦那个 3332 将组群内的成员加到自己的通讯录中,最后返回调用成功。

这个时候再尝试让 3333 加入 3332(即 3332 和 3331)所在的群组中:

JS 实现区块链分布式网络

同样的步骤:

3333 先尝试加入这个家庭:

JS 实现区块链分布式网络

3331 和 3332 接收了新成员:

JS 实现区块链分布式网络

成功后 3333 将 3331 和 3332 加入到自己的通讯录中,完成加入。

现在的问题就是,每一个结点有着单独一个 blockchain 的 instance,而在现实生活中,所有的网络节点都在同一个区块链上工作。

下一步就会尝试解决这个问题。文章来源地址https://www.toymoban.com/news/detail-456033.html

到了这里,关于JS 实现区块链分布式网络的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 区块链的分布式账本

    定义 整个区块链网络运行的核心信息流 特征; 工作原理 区块链账本+状态库 即存储序列集的区块链账本和表达区块链当前所有账户状态的状态库 注释1: 1.区块链: 注释2: 2.状态库 ####技术支撑 1.非对称加密 2.哈希散列计算

    2024年02月11日
    浏览(53)
  • 区块链技术之分布式存储

    随着互联网技术应用技术的普遍使用,所有行业的数据量指数级增长,数据存储技术都需要更新。分布式存储是一种数据存储技术,它可以跨多个物理服务器传播文件、块存储或者对象存储,以实现高可用性、数据备份和灾难恢复目的。可扩展的存储服务以及数据中心的巨大

    2024年02月16日
    浏览(56)
  • 分布式账本-区块链核心技术之一

    id:BSN_2021 公众号:BSN研习社 区块链是一种多项计算机技术的集成融合创新。在这众多来源中,最重要的一个是分布式账本技术。 分布式账本指的是交易记账由分布在不同地方的多个节点共同完成,而且每一个节点记录的是完整的账目,因此它们都可以参与监督交易合法性,

    2024年02月15日
    浏览(60)
  • 分布式系统中的区块链应用

    作者:禅与计算机程序设计艺术 分布式系统正在成为越来越多的企业级应用的架构模式。越来越多的应用从单机数据库扩展到分布式系统,通过无缝集成服务框架,实现了数据可靠性、服务高可用、容错等目标。但是传统的分布式系统没有引入更加先进的技术,如区块链技术

    2024年02月12日
    浏览(47)
  • Tangle:不同于区块链的分布式账本

    现在,我们可以使用基于DAG(有向无环图)和Tangle的马尔可夫链蒙特卡罗算法的不同架构,而不是使用区块链来表示数据的不变性和来源。该数据结构被IOTA项目用作其物联网的DLT(分布式账本技术)。 像区块链一样,Tangle也是一个分布式数据库,它可以不可更改地透明地存储加

    2024年01月15日
    浏览(51)
  • 基于区块链的分布式存储系统开发论文研究

    论文引用:[1]蔡维德,郁莲,王荣,刘娜,邓恩艳.基于区块链的应用系统开发方法研究[J].软件学报,2017,28(06):1474-1487. 1. 区块链介绍   区块链是由多独立节点参与的分布式数据系统,也可以理解为分布式账簿(distributed ledger technologt,简称DLT),由这些节点共同维护,它的特点是

    2024年02月12日
    浏览(61)
  • 3、漫谈分布式系统、拜占庭将军问题与区块链

    分布式系统和一致性问题 拜占庭将军问题 我们前面讨论的一致性协议,有一个重要的前提条件,就是:各个节点都是可以信任的,它们都严格遵守同样的一套规则。这个条件,在一个公司的内部网络中可以认为是基本能满足的。但如果这个条件不满足会怎么样呢?假设网络

    2024年02月03日
    浏览(53)
  • 架构师必知必会系列:区块链与分布式账本

    作者:禅与计算机程序设计艺术 区块链,又称分布式数据库,是一个P2P网络,采用点对点的方式,将所有数据记录在不断增加的区块中,每个区块都具有校验功能,利用密码学的方法保证数据不被篡改。其主要优点如下: 可追溯性:任何一方都可以验证任意时刻上链的数据

    2024年02月08日
    浏览(59)
  • 区块链的五个基本特征与传统分布式系统的区别

    区块链是分布式数据存储,点对点传输,共识机制,加密算法等计算机技术在互联网时代的创新应用模式。虽然不同报告中对区块链的介绍措辞不尽相同,但“去中心化、开放性、自治性、信息不可篡改和匿名性”这五个基本特征得到了共识性。 1.去中心化 所谓去中心化,

    2024年02月02日
    浏览(53)
  • XuperSocial首个明星DApp上线,探索区块链分布式通信基础设施

    12月7日,星际口袋上线星际社区,为广大藏友提供稳定、可信的交流场所。 星际社区基于百度超级链团队重磅发布的去平台化社交解决方案XuperSocial搭建,XuperSocial是架设在百度超级链开放网络(XuperOS)上的DApp,它能够帮助任何Web3业务方搭建自己的Web3社区。 XuperSocial的运行

    2024年02月02日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包