我仅用50 行 JavaScript 代码从头构建区块链,向你介绍区块链的工作原理

f6d8e5dd8a482addf0cbd54616443aed.png

英文 | https://medium.com/geekculture/blockchain-explained-in-50-lines-of-code-1dbf4eda0201

翻译 | 杨小爱

区块链,区块链,区块链!在过去的十年里,我们一次又一次地听到这个技术流行语。它被认为是 21 世纪最重要的发明之一。

如果您听说过区块链但不完全了解它,那没关系!今天的文章中,我将通过仅使用 50 行 JavaScript 代码从头构建区块链,向您展示区块链的工作原理。

在我们开始之前,我想指出,如果您了解一些基本的编程知识,这篇文章会更容易理解。但是如果你没有编程知识,你也不要担心,因为我会尽力详细解释每一段代码。

现在,让我们开始吧!

首先,我们需要了解区块链是如何创建的。

区块链,顾名思义,是由多个区块链连接在一起形成的。

56d7aaae7489de0e83320758380fc1b4.png

每个块通常包含以下信息:

  • 数据:这可以是交易数据之类的任何东西。

  • 哈希值:这基本上是块的 ID。

  • 前一个哈希值:这会跟踪前一个块 ID。现在,你只需要知道我们使用这个值在当前块和前一个块之间形成一个链。我将在本文后面解释为什么这个值很重要。

  • 时间戳:这告诉我们区块何时被创建。

  • 工作量证明:这是一个数字,显示了找到当前块的哈希值的努力。如果你听说过挖矿,这个值代表机器计算哈希值需要多长时间(以数字的形式)。

在现实世界中,块比这更复杂,但我想尽量保持简单:)

让我们进入有趣的部分,编码!

1、创建块类

让我们在一个空的 index.js 文件中创建一个名为“Block”的类。

251971e9a7620250951991aa0b4f29cd.png

此类的构造函数接受 2 个参数。第一个是前一个区块的哈希值,第二个是当前区块的数据。

在构造函数内部,我们使用构造函数参数初始化块数据。我们将 timeStamp 设置为当前时间,将 proofOfWork 设置为 0。

还记得我说过我们需要计算哈希值吗?是的,哈希值不仅仅是一个随机字符串,为了安全起见,我们需要根据当前数据和之前的哈希值来找到当前的哈希值。

如果黑客更改了一个区块的数据,他们还必须重新计算前面所有区块的哈希值以使链有效(如果他们和我使用同一台计算机,这可能需要数千年)

对于那些不了解哈希的人,它基本上是我们如何将数据转换为一堆随机字符。例如,单词“hello”可以散列成“e2d48e7bc...”。因为散列只在一个方向上起作用,所以很容易找到给定输入的散列输出,但很难从散列输出中预测输入。

我们来看一下calculateHash函数。

687a3d0faa6d1229f292466802f58ff0.png

该函数基本上根据之前的哈希值、当前数据、当前时间戳和工作量证明的组合生成一个哈希值。

我们使用来自 crypto-js npm 包的哈希函数。这个包基本上允许我们使用几种散列方法。我们在本教程中使用安全哈希算法 256 (SHA 256)。如您所见,我们在文件顶部导入哈希。

我们来看看 Block 类的最终功能。mine功能。

这个mine函数不断增加,直到proofOfWork帮我们找到一个以我们想要的数字,如0开头的哈希值(我们称之为难度)。难度越高,创建哈希所需的时间就越长。这是因为从哈希输出中找到输入的唯一方法就是,不断尝试不同的输入。

有趣的事实:比特币区块的哈希值需要 18 个零,其区块链网络中的所有计算机大约需要 10 分钟才能创建。

如果您听说过人们谈论挖掘加密货币,这就是它的工作原理。他们投资超级机器来计算新区块的哈希值,并获得一些加密货币作为奖励。

你可能想知道为什么它必须那么复杂?

想象一下,如果创建哈希既简单又快速,那么存储在区块链中的数据将很容易被更改。因此,哈希值是以如此复杂的方式创建的,因此即使一个块被黑客入侵,也需要永远更新以下所有块。这就是区块链如此安全的原因。

如果你读到这里,请随意拍拍自己的后背,因为我们已经成功地在区块链中创建了一个区块。

下一部分是创建区块链来存储所有块。

2、创建区块链类

让我们创建Blockchain类

c87dcc4b2d0edb3797f4ed8e90c0c084.png

我们的区块链存储 1 个名为 chain 的数组。我们还将向链中添加一个 genesisBlock。genesis block 它基本上是链中的第一个块。因此,我们可以传递“0”作为前一个哈希值,因为没有前一个块。

接下来,我们将实现 addBlock 函数,该函数将一个新块添加到链中。

该函数接受新数据作为参数,并根据该数据和前一个区块的哈希值创建一个新区块。

dfda6019d9fb3d829fddab35c526c79c.png

请记住,当我们创建一个新块时,我们必须使用 mine 函数计算其哈希值。为了使它更快,我只将 diffifulty 设置为 2,因此,新的哈希值必须以 2 个零开头。

找到哈希值后,我们只需要将新块添加到链中。

最后,我们需要 isValid 函数来验证当前链是否有效。

这个函数基本上遍历每个块(except the genesis one)并检查哈希值是否存在任何违规。如果没有违规,则返回 true。

恭喜!您已成功构建区块链。

让我们在下面的示例部分看看它是如何工作的。

3、使用示例

让我们尝试将包含转换信息的 2 个新块添加到我们的区块链。

ad980fd64524b2502b5fdafc5d09cbdd.png

添加这两个值后,我们的区块链将如下所示。

8b9f591ccd2c86b0840cfb0e9ab7b15a.png

如果您注意到,每个块的 previousHash 与它之前的块的哈希完全相同。

你想象一下,作为第一笔交易的接收方的大卫,他想要更多的钱,并像这样修改区块的数据。

cdd3ebbf82f95d8c53afef7e618e5473.png

区块链将无效,因为第一个区块的新哈希值与其先前计算的哈希值不同。

b31565aa1cbde460ce1c13b693f003f2.png

很好的尝试,大卫!金额可能会改变,但对整个区块链是无效的。大卫必须重新计算每个块的哈希值,并以使其都有效。这在现实生活中是不可能实现的!

总结

以上就是我所要分享的文章内容。我希望对您想更多地了解区块链会有所帮助。如果您觉得今天内容对您有所帮助,也请您分享给您的朋友,也许也可以帮助到他。

如果您有任何问题,请在留言区给我留言,我知道的,一定都与您分享。

感谢您的阅读。

另外,一些是这本中的完整代码:

const hash = require("crypto-js/sha256");
class Block {
  constructor(previousHash, data) {
    this.data = data;
    this.hash = this.calculateHash();
    this.previousHash = previousHash;
    this.timeStamp = new Date();
    this.proofOfWork = 0;
  }


  calculateHash() {
    return hash(
        this.previousHash + 
        JSON.stringify(this.data) +
        this.timeStamp +
        this.proofOfWork
    ).toString();
  }


  mine(difficulty) {
    while (!this.hash.startsWith("0".repeat(difficulty))) {
      this.proofOfWork++;
      this.hash = this.calculateHash();
    }
  }
}


class Blockchain {
  constructor() {
    let genesisBlock = new Block("0", { isGenesis: true });
    this.chain = [genesisBlock];
  }


  addBlock(data) {
    let lastBlock = this.chain[this.chain.length - 1];
    let newBlock = new Block(lastBlock.hash, data);
    newBlock.mine(2); // find a hash for new block
    this.chain.push(newBlock);
  }


  isValid() {
    for (let i = 1; i < this.chain.length; i++) {
      const currentBlock = this.chain[i];
      const previousBlock = this.chain[i - 1];
      if (currentBlock.hash != currentBlock.calculateHash()) return false;
      if (currentBlock.previousHash != previousBlock.hash) return false;
    }
    return true;
  }
}

看,没有点击诱饵!它正好有 50 行😊

喜欢的话,请记得关注我,点赞我,非常感谢。

学习更多技能

请点击下方公众号

673f35451b4a179289b71d62257b7b6f.gif

21b10013b2ffb1c294a7732aeeb6cbb7.png

97564cf8351ea26dd197d9f2765f5e0d.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值