JS 实现区块链分布式网络

JS 实现区块链网络

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

需要安装的依赖有:

  • express

  • body-parser

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

  • request

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

  • request-promise

可选的依赖包包括:

  • concurrently
  • nodemon

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

⚠️:requestrequest-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', 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}` });
});

测试结果如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

⚠️:重复一下,在当前 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', 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) => {
    // ...
  };
}

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

实现去中心化区块链网络

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

在这里插入图片描述

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

  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,所以这么修改的,如果不用一样的配置,可能需要自己想办法修改一下参数的问题。

运行结果如下:

在这里插入图片描述

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

post register node

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

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

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

app.post('/register-node', 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.' });
});

在这里插入图片描述

在这里插入图片描述

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

post register nodes bulk

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

实现如下:

app.post('/register-nodes-bulk', 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.' });
});

测试如下:

在这里插入图片描述

在这里插入图片描述

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

post register & broadcast

实现如下:

app.post('/register-and-broadcast-node', 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.' });
    });
});

测试结果如下:

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

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

在这里插入图片描述

同样的步骤:

3333 先尝试加入这个家庭:

在这里插入图片描述

3331 和 3332 接收了新成员:

在这里插入图片描述

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

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

下一步就会尝试解决这个问题。

原文地址:https://blog.csdn.net/weixin_42938619/article/details/130518652

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读903次。文章主要介绍了收益聚合器Beefy协议在币安智能链测试网网上的编译测试部署流程,以Pancake上的USDC-BUSD最新Curve版流动池的农场质押为例,详细介绍了完整的操作流程。_怎么在bsc网络上部署应用
文章浏览阅读952次。比特币的主要思路是,构建一个无中心、去信任的分布式记账系统。交易签名只能保证交易不是他人伪造的,却不能阻止交易的发起者自己进行多重交易,即交易的发起者将一个比特币同时转账给两个人,也就是所谓的双花。比特币应用的区块链场景也叫做公链,因为这个区块链对所有人都是公开的。除此之外,还有一种区块链应用场景,被称作联盟链。区块链的出现,使得低成本,去信任的跨组织合作成为可能,将重构组织间的关系,这个关系既包括企业间的关系,也包括政府和企业间的关系,还有政府部门间的关系。
文章浏览阅读2.5k次。虚拟人从最初的不温不火,到现在步入“出生高峰期”,元宇宙可以说是功不可没。此前,量子位发布了《虚拟数字人深度产业报告》,报告显示,到2030年我国虚拟数字人整体市场规模将达到2700亿元。其中,“身份型虚拟人”市场规模预计达到1750亿元,占主导地位,而“服务型虚拟人”总规模也将超过950亿元。得益于AI、VR/AR 等技术的发展,虚拟人的应用场景正在从传统的虚拟偶像等娱乐行业迈向更多元化的领域。_最喜欢的虚拟角色
文章浏览阅读1.3k次,点赞25次,收藏13次。通过调查和分析用户需求、兴趣和行为,你可以更好地定位你的目标受众,并在市场中找到你的定位。在设计你的Web3.0项目时,注重用户界面的友好性、交互流畅性和功能的创新性,以提供独特的用户体验。通过与有影响力的人或组织进行合作,推广你的Web3.0项目。通过与他们分享你的项目并抓住他们的推荐,可以迅速获得更多的关注度。通过优化你的网站和内容,将有助于提高你的排名,并增加有机流量。通过提供奖励激励计划,如空投、奖励机制等,激励用户参与你的Web3.0项目。的人或组织合作,可以增加你的项目的曝光度。
文章浏览阅读1.7k次。这个智能合约安全系列提供了一个广泛的列表,列出了在 Solidity 智能合约中容易反复出现的问题和漏洞。Solidity 中的安全问题可以归结为智能合约的行为方式不符合它们的意图。我们不可能对所有可能出错的事情做一个全面的列表。然而,正如传统的软件工程有常见的漏洞主题,如 SQL 注入、缓冲区超限和跨网站脚本,智能合约中也有反复出现的。_solidity安全漏洞
文章浏览阅读1.3k次。本文描述了比特币核心的编译与交互方法_编译比特币
文章浏览阅读884次。四水归堂,是中国建筑艺术中的一种独特形式。这种形式下,由四面房屋围出一个天井,房屋内侧坡向天井内倾斜,下雨时雨水会从东西南北四方流入天井,从而起到收集水源,防涝护屋的作用,寓意水聚天心,天人合一。在科技产业当中,很多时候我们需要学习古人的智慧与意蕴,尝试打通各个生态,聚四方之力为我所用,这样才能为最终用户带来最大化价值。随着数字化、智能化的发展,算力成为生产力的根基。在这一大背景下,算力需要贯通软..._超聚变csdn
文章浏览阅读1k次,点赞24次,收藏19次。云计算和区块链是当代科技领域两个备受关注的核心技术。本文将深入探讨云计算和区块链的发展历程,详细剖析其起初阶段的奠基、面临的问题、业务内容、当前研究方向、用到的技术、实际应用场景、未来发展趋势,并提供相关链接供读者深入了解。
文章浏览阅读1.5k次。融入对等网络的奥妙,了解集中式、全分布式和混合式对等网络的差异,以及区块链网络的结构与协议,让你跃入区块链的连结网络。揭开密码学的神秘面纱,探寻对称密码学、非对称密码学、哈希函数、数字签名等关键技术,让你了解信息安全的核心。解码共识算法的精髓,从理论到实践,从PoW、PoS到PBFT,让你深入了解区块链如何达成共识。探索智能合约的世界,从定义到生命周期,从执行引擎到开发与部署,带你进入无限可能的合约领域。了解令人惊叹的区块链世界,从概念到价值,从发展历程到政策法规,一篇章串联出区块链的精髓。
文章浏览阅读777次。8 月份,加密货币市场经历了明显的波动,比特币价格波动幅度较大。与此同时,NFT 市场出现大幅下跌,引发了人们对这一新兴行业未来发展趋势的担忧
文章浏览阅读8.8k次,点赞53次,收藏37次。近二十年来,我国信息科技发展日益成熟,出现的网络完全问题也是“百花齐放”。而元宇宙作为5G技术、AR/VR技术、云计算以及区块链等技术的组合体,其安全性指定会被人们所广泛关注。根据前面所讲,元宇宙融合了虚拟世界和现实世界,通过数据将现实世界的各种元素映射到数字化的虚拟世界中。所以没有数据,就等于没有元宇宙的一切;没有信息安全,元宇宙的社会生产、生活就不能正常有序地进行。所以足以可见数据安全、信息安全对元宇宙发展起到的重要作用!!_元宇宙 安全计算
文章浏览阅读1.4k次。最早使用历史 1991年采用 时间戳 追溯 数字文档,之后 2009年后创始人**中本聪** (satoshi nakamoto )日裔美国人,在设计比特币数字货币中将此理念写入应用程序中_web3.0学习
文章浏览阅读1.7k次。DeFi收益来源全面概述_drfi收益
文章浏览阅读941次,点赞17次,收藏21次。号外:教链内参1.28《从BTC现货ETF的近期数据看到的》隔夜BTC经历现货ETF通过后的情绪冷静,一度破位40k后又逐渐修复至42k上方。请珍惜42k的BTC吧。也许到下个周期,我们将不再有机会见到这个高度的BTC了。下面,让我们重温,42k的BTC,在过去四年穿越牛熊的过程中,带给我们的启迪吧。需要提醒的是,历史文字,自有历史局限性,回顾,也须带着批判性的目光阅读和审视。2021年2月8日,...
文章浏览阅读1.2k次,点赞23次,收藏21次。其实一开始我也是这么想的,但根据PoW算法机制,如果你的计算量不够大,是无法控制区块链的走向的,也就是说,即使你投入了大量的成本用于完成任务,也不能保证自己成功。例如,你持有100个币,总共持有了30天,那么,此时你的币龄就为3000,这个时候,如果你发现了一个PoS区块,那么你的币龄就会被减去一定的值,每减少365个币龄,将会从区块中获得0.05个币的利息(可理解为年利率5%),那么在这个案例中,利息=3000×5%/365=0.41个币。前面说过,谁的算力强,谁最先解决问题的概率就越大。
文章浏览阅读1.9k次。这里主要实现的部分继续下去,对 Blockchain 这个对象有一些修改,如果使用 TS 的话可能要修改对应的 interface,但是如果是 JS 的话就无所谓了。需要安装的依赖有:express现在的 express 已经不内置 body-parser,需要作为单独的依赖下载request不下载会报错,是使用 request-promise 所需要的依赖和已经 deprecated 了,具体 reference 可以参考。_js区块链
文章浏览阅读1k次,点赞19次,收藏19次。作者:Zach Pandl Grayscale编译:象牙山首席村民 碳链价值以太坊在2023年取得了丰厚的回报。但表现不如比特币以及其他一些智能合约公链代币。我们认为,这反映了今年比特币特有的积极因素以及以太坊链上活动的缓慢复苏。尽管以太坊的涨幅低于比特币,但从绝对值和风险调整值来看,今年以太坊的表现优于传统资产类别。以太坊不断增长的L2生态系统的发展可能会吸引新用户,并在2024年支撑以太币的...
文章浏览阅读908次,点赞20次,收藏20次。通证是以数字形式存在,代表的是一种权利、一种固有和内在的价值。徐教授告诉我:多年的职业经历,多年的为易货贸易的思考,认识到在处理贸易和经济领域的关系时,应以提高人民生活水平、保证社会成员充分就业、保证就业成员实际收入和有效需求的大幅稳定增长、实现世界资源的充分利用以及扩大货物的生产和交换为目的,期望通过达成互惠互利安排,实行公开、公平、公正的“三公原则”,开展国家与国家、企业与企业之间的易货贸易,规避因信用问题引起的各类风险,消除国际贸易中的歧视待遇,促进全球国家的经济发展,从而为实现上述目标做出贡献。
文章浏览阅读2.5k次。由于webase文档原因,查找起来比较局限,有时候想找一个api却又忘了在哪个模块的目录下,需要一步一步单独点,而利用文档自带的检索功能又因为查找文档全部信息,显得十分缓慢,所以整理了有关WeBASE的api列表但不可否认,现在只有列表,没有对应的页面跳转,文章目的也只是为了多了解webase的接口_webase私钥管理里获取
文章浏览阅读1.4k次,点赞28次,收藏21次。基于​openzeppelin来构建我们的NFT,并用一个例子来手把手的说明如何在opensea快速发布自己的NFT智能合约(ERC721)。