以太坊作为目前最智能的平台和区块链操作系统之一,其强大的去中心化应用(DApps)开发能力吸引了全球开发者,对于许多 JavaScript 开发者而言,利用熟悉的语言与以太坊生态系统交互是进入区块链领域的自然选择,而搭建以太坊私链,则是在无需担心成本和安全风险的前提下,进行开发、测试和实验的理想选择,本文将详细介绍如何使用 JavaScript 及相关工具来搭建和交互以太坊私链。
为什么选择 JavaScript 与以太坊私链
- 熟悉的语言环境:JavaScript 是全球使用最广泛的编程语言之一,Node.js 的出现使其具备了强大的后端开发能力,对于前端开发者或全栈开发者来说,使用 JavaScript 处理区块链逻辑可以降低学习成本。
- 丰富的库与框架支持:以太坊社区为 JavaScript 开发者提供了众多成熟的库,如
web3.js、ethers.js等,极大地简化了与以太坊节点交互的复杂性。 - 私链的优势:
- 低成本:无需花费真实的以太坊(ETH)进行测试和部署。
- 高速度:私链的出块速度和交易确认速度远快于公有链,适合快速迭代开发。
- 安全性可控:可以完全控制网络节点,无需担心外部攻击或恶意行为。
- 定制化:可以根据需求调整区块链参数,如区块大小、出块时间、共识算法等。
搭建以太坊私链的核心工具
在 JavaScript 生态中,搭建以太坊私链最常用的工具是 Geth(Go-Ethereum)配合 Node.js 以及相关的 JavaScript 库。
- Geth (Go-Ethereum):以太坊官方的 Go 语言实现,是最流行的以太坊客户端之一,它功能强大,支持全节点、轻节点、矿工、智能合约部署等多种角色,搭建私链通常使用 Geth 的
--dev模式或通过自定义创世块的方式。 - Node.js:JavaScript 的运行时环境,用于运行我们的 JavaScript 脚本和工具。
- Web3.js / Ethers.js:JavaScript 库,用于与以太坊节点进行交互,如发送交易、调用合约、查询状态等。
ethers.js以其更现代的 API 设计和对 EIP-1193 标准的良好支持而越来越受欢迎。

使用 JavaScript 搭建以太坊私链(以 Geth + ethers.js 为例)
安装必要环境
- 安装 Node.js 和 npm:从 Node.js 官网 下载并安装 LTS 版本。
- 安装 Geth:
- Windows:下载 Geth 安装包或使用
scoop等包管理器。 - macOS:使用
brew install geth。 - Linux:使用
apt-get install geth(Ubuntu/Debian) 或从源码编译。 - 确保将 Geth 的可执行文件路径添加到系统环境变量
PATH中,以便在命令行中直接调用geth命令。
- Windows:下载 Geth 安装包或使用
启动私链节点
最简单的方式是使用 Geth 的 --dev 模式,它会自动创建一个包含预挖区块和测试账户的私有开发网络。
打开终端,运行以下命令:
geth --dev --http --http.addr "0.0.0.0" --http.port "8545" --http.api "eth,net,web3,personal"
命令参数说明:
--dev:启动开发模式,创建一个全新的私有链,包含一个预分配了 10000 ETH 的测试账户,并自动挖矿。--http:启用 HTTP-RPC 服务,允许通过 HTTP API 访问节点。--addr "0.0.0.0":监听所有网络接口,方便本地或其他机器访问。--http.port "8545":指定 HTTP-RPC 服务的端口号,默认是 8545。--http.api "eth,net,web3,personal":暴露指定的 API 接口。
启动后,Geth 会开始同步区块(在 --dev 模式下会很快),并自动开始挖矿,你会看到类似 Mining started 的输出。
使用 JavaScript (ethers.js) 与私链交互
-
初始化项目并安装
ethers.js:在新的项目目录下,运行:
npm init -y npm install ethers
-
编写交互脚本:
创建一个
interact.js文件,编写以下代码:const { ethers } = require("ethers"); // 1. 连接到私链的 HTTP-RPC 端点 const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545"); // 2. 获取链信息(可选) console.log("Connected to network:", (await provider.getNetwork()).name); console.log("Chain ID:", (await provider.getNetwork()).chainId); console.log("Latest block number:", await provider.getBlockNumber()); // 3. 获取 dev 模式下默认的测试账户 // 在 --dev 模式下,Geth 会创建一个默认账户,其私钥是固定的 // 注意:在实际项目中,不要硬编码私钥!这里仅用于演示 dev 模式 const devPrivateKey = "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"; // geth --dev 默认账户私钥 const wallet = new ethers.Wallet(devPrivateKey, provider); console.log("\nDefault account address:", wallet.address); console.log("Default account balance:", ethers.utils.formatEther(await wallet.getBalance())); // 4. 发送一笔交易(从一个账户转账到另一个新账户) // 创建一个新账户作为接收方 const receiverWallet = ethers.Wallet.createRandom(); console.log("\nReceiver address:", receiverWallet.address); console.log("Receiver initial balance:", ethers.utils.formatEther(await provider.getBalance(receiverWallet.address))); // 构建并发送交易 const tx = await wallet.sendTransaction({ to: receiverWallet.address, value: ethers.utils.parseEther("0.1"), // 转账 0.1 ETH gasLimit: 21000, // 转 ETH 的标准 gas 限制 gasPrice: await provider.getGasPrice() // 获取当前建议的 gas 价格 }); console.log("\nTransaction hash:", tx.hash); console.log("Waiting for transaction to be mined..."); // 等待交易被打包 await tx.wait(); console.log("Transaction mined!"); // 检查转账后的余额 console.log("Sender balance after tx:", ethers.utils.formatEther(await wallet.getBalance())); console.log("Receiver balance after tx:", ethers.utils.formatEther(await provider.getBalance(receiverWallet.address))); -
运行脚本:
在终端中运行:
node interact.js
你应该能看到脚本成功连接到私链,获取账户信息,并执行了转账交易,最终打印出交易前后的余额变化,Geth 终端中也会显示新的区块被挖出。
进阶:自定义创世块与多节点私链
对于更复杂的测试场景,可能需要自定义创世块或搭建多节点私链。
-
自定义创世块:
- 创建一个
genesis.json文件,定义创世区块的配置,如链 ID、初始账户列表、共识算法(如 clique 用于 PoA)、难度等。 - 使用
geth --datadir "./mychain" init genesis.json命令用该创世文件初始化数据目录。 - 使用
geth --datadir "./mychain" --networkid 12345 --http --http.addr "0.0.0.0" --http.port "8545"启动节点,--networkid用于区分不同的网络。
- 创建一个
-
多节点私链:
- 为每个节点创建独立的数据目录和创世块(共享同一个 genesis.json)。
- 每个节点需要配置不同的端口(P2P 端口和 HTTP-RPC 端口)。
- 在节点的
geth.config或启动命令中通过--bootnodes指定其他节点的 enode 地址,使它们能够互相发现和连接。 - 在 PoA