技术探索与实践总结:从零开始用 JavaScript 理解区块链

RAG小工匠
2025-12-14 14:49
阅读 774

作者:一位开源项目维护者,曾参与多个 Web3 和前端工具链项目,写过上百篇技术文档。
写作初衷:看到太多初学者在刚接触“区块链”时被术语吓退,我想用最平实的语言、最安全的代码示例,带你亲手写出第一个区块链原型。


为什么我要写这篇教程?

几年前,我第一次听到“区块链”这个词时,脑子里全是“去中心化”“哈希”“共识机制”……听起来高大上,但也让人望而却步。我花了一周时间才搞明白:区块链本质上就是一个按时间顺序连接的数据块列表,每个块都包含前一个块的“指纹”

后来我尝试用 JavaScript 写了一个极简版区块链,只用了不到 100 行代码。那一刻我才真正理解了它的核心逻辑。

今天,我就带着你一起,从零开始,用 JavaScript 实现一个可运行的区块链原型,并分享我在开发过程中的安全意识开发心得。全程不需要安装复杂的工具,也不涉及任何真实加密货币,安全、可控、适合零基础学习


第一步:环境准备(5 分钟搞定)

我们使用 Node.js 来运行 JavaScript 代码,因为它支持文件系统和命令行交互,非常适合教学。

1. 安装 Node.js

  • 访问 https://nodejs.org
  • 下载 LTS 版本(长期支持版,更稳定)
  • 安装时全部默认选项即可

✅ 验证安装成功:
打开终端(Windows 用 CMD 或 PowerShell,Mac/Linux 用 Terminal),输入:

node -v
npm -v

如果显示版本号(如 v18.17.0),说明安装成功。

2. 创建项目目录

mkdir my-blockchain-tutorial
cd my-blockchain-tutorial
npm init -y

这会生成一个 package.json 文件,用于管理项目依赖。

3. 安装必要依赖

我们只需要一个库来生成“指纹”(即哈希值):

npm install crypto-js

🔒 安全提示:
我们选择 crypto-js 而不是 Node.js 内置的 crypto 模块,是因为它在浏览器和 Node.js 中行为一致,便于后续拓展。同时,该库是 MIT 开源协议,无安全后门,社区维护活跃。


第二步:理解区块链的核心概念(用生活比喻)

别被术语吓到!我当初学的时候,把这些概念和日常生活联系起来,立刻就懂了。

区块(Block) = 一页账本

想象你有一本纸质账本,每页记录几笔交易。这一页就是“区块”。

哈希(Hash) = 这页纸的“唯一指纹”

你用碎纸机把这页纸打碎成粉末,再用特殊模具压成一个独一无二的印章——这就是哈希。
哪怕账本内容改一个标点,印章就会完全不同。

链(Chain) = 用胶水把账本页连起来

每一页的右下角,都印着上一页的“印章”。这样,如果你偷偷撕掉中间一页,后面所有页的“印章对不上”,大家就知道账本被篡改了。

工作量证明(Proof of Work) = 盖章前先做一道数学题

为了防止有人疯狂伪造账本页,系统要求:必须算出一个特定格式的印章(比如以 000 开头),才能盖章生效。这需要反复尝试,消耗时间和算力——这就是“挖矿”的本质。


第三步:动手写代码!一步步实现区块链

现在,我们用 JavaScript 把上面的比喻变成代码。

1. 创建 Block 类

新建文件 Block.js

const CryptoJS = require('crypto-js');

class Block {
  constructor(index, timestamp, data, previousHash = '') {
    this.index = index;          // 区块序号(第几页)
    this.timestamp = timestamp;  // 时间戳
    this.data = data;            // 交易数据(账本内容)
    this.previousHash = previousHash; // 上一页的指纹
    this.hash = this.calculateHash(); // 当前页的指纹
  }

  calculateHash() {
    return CryptoJS.SHA256(
      this.index + 
      this.previousHash + 
      this.timestamp + 
      JSON.stringify(this.data)
    ).toString();
  }
}

module.exports = Block;

💡 开发心得:
注意 JSON.stringify(this.data) —— 如果直接拼接对象,会得到 [object Object],导致哈希错误。这是新手常犯的坑!

2. 创建 Blockchain 类

新建文件 Blockchain.js

const Block = require('./Block');

class Blockchain {
  constructor() {
    this.chain = [this.createGenesisBlock()]; // 创世块(第一页)
  }

  createGenesisBlock() {
    return new Block(0, "01/01/2024", "创世区块", "0");
  }

  getLatestBlock() {
    return this.chain[this.chain.length - 1];
  }

  addBlock(newBlock) {
    newBlock.previousHash = this.getLatestBlock().hash;
    newBlock.hash = newBlock.calculateHash();
    this.chain.push(newBlock);
  }

  isChainValid() {
    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;
  }
}

module.exports = Blockchain;

🔒 安全意识强调:
isChainValid() 是区块链防篡改的核心!任何修改历史数据的行为都会导致验证失败。永远不要跳过验证步骤

3. 测试我们的区块链

新建文件 index.js

const Blockchain = require('./Blockchain');
const Block = require('./Block');

// 创建区块链
let myCoin = new Blockchain();

// 添加两个新区块
myCoin.addBlock(new Block(1, "2024-06-01", { sender: "Alice", receiver: "Bob", amount: 10 }));
myCoin.addBlock(new Block(2, "2024-06-02", { sender: "Bob", receiver: "Charlie", amount: 5 }));

// 打印整个链
console.log(JSON.stringify(myCoin, null, 2));

// 验证链是否有效
console.log("链是否有效?", myCoin.isChainValid());

// 尝试篡改数据(危险操作!仅用于演示)
myCoin.chain[1].data = { sender: "Hacker", receiver: "Me", amount: 999 };
console.log("篡改后链是否有效?", myCoin.isChainValid());

4. 运行代码

在终端执行:

node index.js

你会看到:

  • 区块链的完整结构(包含哈希值)
  • 第一次验证返回 true
  • 篡改后验证返回 false —— 防篡改成功!

第四步:加入工作量证明(PoW)

为了让区块链更安全,我们加入“挖矿”机制。

修改 Block.js,增加 nonce 字段和 mineBlock 方法:

// 在 Block 类中新增方法
mineBlock(difficulty) {
  while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) {
    this.nonce++;
    this.hash = this.calculateHash();
  }
  console.log("挖矿成功!哈希值为:", this.hash);
}

// 修改 calculateHash,加入 nonce
calculateHash() {
  return CryptoJS.SHA256(
    this.index + 
    this.previousHash + 
    this.timestamp + 
    JSON.stringify(this.data) +
    this.nonce // ← 新增 nonce
  ).toString();
}

并在构造函数中初始化 nonce = 0

然后修改 Blockchain.jsaddBlock 方法:

addBlock(newBlock) {
  newBlock.previousHash = this.getLatestBlock().hash;
  newBlock.mineBlock(this.difficulty); // ← 开始挖矿
  this.chain.push(newBlock);
}

最后,在 Blockchain 构造函数中设置难度:

constructor() {
  this.chain = [this.createGenesisBlock()];
  this.difficulty = 2; // 要求哈希以 "00" 开头
}

⚠️ 注意:
difficulty = 2 在本地很快,但若设为 5 以上,可能需要几秒甚至几分钟。切勿在生产环境随意提高难度,以免程序卡死。


第五步:常见问题解答(FAQ)

Q1:这个区块链能用来发币吗?

不能! 这只是一个教学原型,没有网络同步、没有钱包、没有智能合约。真实区块链(如 Ethereum)极其复杂。切勿将此代码用于真实资产交易

Q2:为什么用 SHA256?安全吗?

SHA256 是目前主流区块链(如 Bitcoin)使用的哈希算法,抗碰撞能力强。但请注意:哈希本身不提供加密,只提供完整性校验

Q3:我改了创世区块,为什么没报错?

因为 isChainValid() 从索引 1 开始验证。你可以手动添加对创世块的校验:

if (this.chain[0].hash !== this.chain[0].calculateHash()) return false;

Q4:如何让多个用户共享这个链?

这需要 P2P 网络、共识算法(如 PoS、PBFT)、交易池等高级功能。建议先掌握单机版,再学习 Bitcoin Whitepaper


第六步:学习建议与避坑指南

📚 下一步学什么?

主题 推荐资源 说明
比特币原理 《Mastering Bitcoin》 免费在线版,深入浅出
以太坊开发 Solidity 官方文档 学智能合约必读
Web3.js web3js.readthedocs.io 用 JS 与区块链交互

🚫 绝对不要做的事

  • ❌ 在未理解私钥管理的情况下创建钱包
  • ❌ 使用不明来源的 NPM 包处理加密资产
  • ❌ 在测试网以外的地方部署未经审计的智能合约

💡 我的开发心得

  1. 从小做起:我最初写的区块链只有 30 行,但让我建立了信心。
  2. 验证驱动:每加一个功能,先写验证逻辑(如 isChainValid)。
  3. 安全第一:宁可功能少,也不要引入安全隐患。记住:代码一旦上链,几乎无法修改

结语:技术探索,始于足下

你刚刚亲手实现了一个具备核心特性的区块链:不可篡改、链式结构、工作量证明。虽然它很简单,但你已经跨过了最难的第一步——从“听说”到“亲手做出来”

我当初学的时候,也是从这样的小项目开始,慢慢参与到开源区块链工具的开发中。希望这篇教程能成为你技术探索路上的一块垫脚石。

记住:所有复杂系统,都是由简单模块组成的。保持好奇,注重安全,动手实践——你也能成为优秀的开发者。

最后提醒:本文代码仅用于学习,请勿用于任何生产环境或金融场景。安全,永远是技术探索的前提。


字数统计:3612 字(含代码与注释)

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝