V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zy445566
V2EX  ›  程序员

使用纯 Node.JS 实现的点对点电子现金系统

  •  1
     
  •   zy445566 ·
    zy445566 · 2020-03-09 13:42:54 +08:00 · 1684 次点击
    这是一个创建于 1509 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文提出通过 Node.js 实现区块链系统,并可以实现 Web 在线挖矿。目前系统基本开发完成,将处于测试阶段和最后准备阶段(包括多机可用性测试,文档编写,准备上帝区块,部署引导节点)。而区块链对于大多数开发是神秘的,尤其语言鄙视链的存在,让其它人对于 JS 开发区块链系统有一定偏见。所以我希望能通过本人开发区块链的一些经历把区块链的技术要点做一些简单的分享。

    本文开发区块链源码地址:FitBlock 仓库地址

    剧前提要

    SHA-256 是一种摘要算法,和大家熟悉的 MD5 算法类似,就是将大量或少量数据来生成几乎唯一的一个极大数。但 SHA-256 长度偏长且摘要算法更加安全。

    ecdsa-secp256k1 是一种椭圆加密算法,可以将私钥推导出公钥。且通过私钥加密,公钥可以验证签名是否正确,而且几乎无法通过公钥推算出私钥的算法,这里亦使用了纯 JS 来实现算法(ecdsa-secp256k1 仓库地址)。

    工作量证明

    何为工作量证明,比如在很多公司喜欢粗暴地将工作时间和工作量挂钩,催生了 996 文化,狗性文化。这属于管理者的一种懒政,或者说通过简单的或低成本方式来验证员工的工作量,至少不用 24 小时盯着你看。那么在程序中,如果计算机是一个只会做运算的工人,如何设计一种算法来通过低成本的方式来计算计算机计算的工作量呢?

    其实答案很简单,举例我需要你在 0 到 1OOO 亿中,使用摘要算法比如 SHA-256 找出开头是 888888 的摘要字符串的那个数字,那么你可能找了好几百万次才找到这个数字,这个数字计算出的摘要字符串开头是 888888。但是我要校验就很简单,只需要将你给我的这个数字,我用相同的摘要算法进行运算得到摘要字符串之后,验证它的前 6 位是否是 8 就可以找到了。

    工作量证明只是方法,存在问题就是如何在计算机算力高速发展或矿工大量罢工导致算力突降的基础上实现工作量的稳定动态增加或动态降低。这点其实很简单比如你计算 6 个 8 的摘要字符串的时间大于十分钟,则我把难度调成下个摘要只需要计算 5 位,如果在十分钟内完成,我把下个摘要增加到计算 7 位。

    钱包和交易

    在现实的理想的世界,你的钱包只有你一个人才能打开,并只有你想要买东西的时候,才会打开钱包为你想买的东西付账。那么在网络世界应该如何实现一个类似钱包的东西呢?

    在剧前提要提到过 ecdsa-secp256k1 椭圆加密算法,这种算法可以使用私钥进行签名,且公钥可以验证签名,且公钥难以反推出私钥。那么我们是不是可以使用私钥作为我们的钱包的钥匙,当我们需要付钱的时候使用私钥进行签名,当别人需要确认交易的时候,只需要将公钥验证交易的签名是否通过,那么这个交易就是经过你授权且有效的。

    那么私钥其实是做了一个取钱的钥匙,那么存钱的入口在哪里? ecdsa-secp256k1 椭圆加密算法有一个重要的特点就是私钥可以推导出公钥,那么公钥是不是就能作为钱包地址即存钱的入口。只要你能通过私钥推导出这个公钥,就证明这个钱包是你的。

    区块链

    那么上面说了工作量证明和交易,那么工作量证明的意义体现在哪里?需要通过什么东西来承载这些交易数据。对!就是区块链。

    什么是区块链?讲区块链前,我认为先讲单独的区块是什么可能更为合理,单独区块可以理解为使用算力的工作量为担保,来证明交易是否真实的证据。那么区块链就很好理解了,通过区块链把这些区块串联起来。

    那么区块是如何串联的呢?在 FitBlock 是这样做的,比如第一个区块链通过工作量证明计算出了一个 888888...666666 即开头是 888888 结尾是 666666 的一个摘要字符串,假设它的高度是 0,那么下一个区块则要计算开头是 666666 的区块,这个时候它的高度是 1,以此类推那么下一个区块则需要再取上个区块摘要结尾的 N 位来计算下一个区块,则下个区块的高度继续加 1。

    那么根据上面的一点,你要推翻一个区块,则需要找到计算出和它一样开头的区块摘要,但是假设目前区块高度是 999,而你要推翻第 1 个区块,那么你要从第一个区块计算到第 1000 个区块,只有你的区块高度大于别人的区块链才表面你有足够的证据推翻,但这个几乎是不可能的,因为每个区块都是根据当前的区块链上算力来推算出,即使你要推翻第高度是 999 的区块,都要使用当前区块链上 51%以上的算力才能推翻上一块。只要所有正义者算力大于 51%,坏人都无法得逞。

    而区块链几乎是无法被篡改,那么你的交易只要接受被矿工接受,并打入区块,你的交易就几乎是无法被篡改的?那么问题来了矿工为什么要为你打包交易进入区块?

    其实在一定高度区块链的区块链中,在某个矿工进行工作证明后出块是有出块奖励。并且你的交易都会有一定交易费给予矿工,保证了矿工的收入。

    P2P 网络

    那么在区块链中传播是一个十分重要的环节,要能即时发现节点并在周围节点启动时能够及时发现节点,包括在内外网络的节点打通问题,该如何处理.

    我认为首先需要一个引导节点尤其是世界上节点较少的时候,引导节点可以使连入的节点快速发现其他节点,通过节点和节点之间的节点分享,快速建立节点网络。其次通过引导节点来引导内网节点来做节点中继,帮助内网也能快速连接到外网的其它节点。

    其次需要保证某个节点只负责一定的范围,这样只要周边节点上线就可以以最快的速度发现节点,同时优先周边节点本身网络距离近,那么网络传输必然比远程节点更加迅速。减少网络的传播时间。

    结语

    第一次使用 JS 实现一个完整的区块链系统。也算是遇到了一些坑,在下次实现区块链系统时,不要以复杂的系统为考虑,提前把系统做的复杂。第二个坑是使用了 GRPC,因为 GRPC 有 Node.js 模块是使用了 C++模块,导致我要前后端使用一个核心库,要重新进行分离。第三过早的使用 Web Components 好处特别轻量,周边过于不完善,对于 CSS 弱没有 UI 库确实比较麻烦。在写这个系统的的时候,我认为最佳部分是使用了 TS,在 TS 的加持下,确实很多东西方便了许多。其次使用 lerna 和 git 的 submodule 管理不同模块,管理和提交都相对清晰。

    3 条回复    2020-03-09 21:44:47 +08:00
    M4ster
        1
    M4ster  
       2020-03-09 17:37:05 +08:00   ❤️ 1
    支持下楼主。其实主网项目已经蛮多了,精品的应用却很少。
    zy445566
        2
    zy445566  
    OP
       2020-03-09 18:20:45 +08:00
    @M4ster 感谢,这个项目可能对于我个人来说可能不错。对于区块链网络来说,算不上精品,这基本就是跟着 BTC 的方案走的,唯一的微创新还是和 Web 挂钩,严格来说还是创新不足。毕竟是个个人产品,能帮助自己和别人了解区块链就足够了。
    yuxizhe
        3
    yuxizhe  
       2020-03-09 21:44:47 +08:00
    nas 就是
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1473 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 17:37 · PVG 01:37 · LAX 10:37 · JFK 13:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.