以太坊私有链完全指南:从环境搭建到智能合约部署

·

常常听到“公链拥堵、手续费飙升”,却苦于没有可控环境做深度测试?从零构建以太坊私有链,可以在本地或内网独立运行一条与主网逻辑一致的区块链:挖矿秒级确认、手续费为零、数据库随时回滚,DApp调试企业链改都更安全高效。本文用一台 Ubuntu 主机为示例,手把手带你完成环境准备、节点启动、创世区块定制、多节点互联,并最终部署一个可查询票据信息的智能合约。关键操作均附带命令行截图级细节,复制粘贴即可复现。


环境清单与前置检查

要素推荐配置
操作系统Ubuntu 16.04/18.04
CPU & 内存双核 2 G 以上
Go-Ethereum1.8.1-stable 及以上
Node.js & npm用于安装 solc 编译器
低于 2 G 内存仍能运行,但挖矿时会出现 out-of-memory,性能测试会失真,强烈建议一步到位。

快速安装 Geth 客户端

打开终端,复制下列命令一次性完成:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo add-apt-repository -y ppa:ethereum/ethereum-dev
sudo apt-get update
sudo apt-get install ethereum

安装结束后运行 geth -h,正常会弹出几十行帮助文档,ethereumgeth 命令就已就绪。


三分钟启动私链(dev 模式)

1. 创建数据目录

mkdir privatechain && cd privatechain

2. 一键脚本 init.sh

nano init.sh

填入内容(按环境把 --rpcaddr 改成你自己的内网 IP):

#!/bin/bash
geth --networkid 123 --dev --datadir data \
  --rpc --rpcaddr 0.0.0.0 --rpcport 8545 --port 30303 \
  --nodiscover --allow-insecure-unlock console
chmod +x init.sh
./init.sh

你会看到类似:

INFO [xx-xx|xx:xx:xx] HTTP endpoint opened: http://0.0.0.0:8545

自此 JSON-RPC 已就绪,MetaMask 或在 Remix 里选择 Web3 Provider 即可直接连。

3. 连接控制台

重开一个终端,输入:

geth attach ipc:./data/geth.ipc

出现 > 提示即进入交互式 JavaScript 环境,可执行 eth, personal, miner 等 API。


核心交互速查表

任务命令
新建账户personal.newAccount("密码")
查看所有账户eth.accounts
查询余额eth.getBalance(eth.accounts[0])
解锁账户发币personal.unlockAccount(eth.accounts[0])
单笔转账eth.sendTransaction({from:..., to:..., value:...})
开始/停止挖矿miner.start(); miner.stop()
查看交易收据eth.getTransactionReceipt(txHash)

用 Mist 钱包所见即所得

Mist(又称 Ethereum Wallet)既可发交易又可可视化部署合约:

# 根据实际路径调整
/path/to/mist --rpc ./data/geth.ipc

首次打开可能会显示“No accounts”,前往控制台执行 personal.newAccount() 即可同步出现。


动手写第一个智能合约

下面示例合约完成“票据 Ticket”的链上增删改查,兼具转账功能,可在 DAO 项目、供应链金融等多种场景落地。

pragma solidity ^0.5.4;

contract SimpleTicket {
    uint public ticketIndex;
    mapping(uint => Ticket) public tickets;

    struct Ticket {
        uint   id;
        string name;
        string content;
        address issuer;
    }

    function addTicket(string memory _name, string memory _content) public {
        ticketIndex += 1;
        tickets[ticketIndex] = Ticket(ticketIndex, _name, _content, msg.sender);
    }

    function getTicket(uint _id) public view returns(uint, string memory, address) {
        Ticket memory t = tickets[_id];
        return (t.id, t.name, t.issuer);
    }
}

命令行编译 + 部署全流程

安装编译器后,依次执行:

npm install -g solc
solcjs --bin --abi SimpleTicket.sol

复制 .bin.abi 文件内容后,回到 Geth 控制台:

var bytecode = "0x6080...";   // 粘贴二进制
var abi      = [/* 粘贴 ABI */];

var myContract = web3.eth.contract(abi);
var estimate   = web3.eth.estimateGas({data: bytecode});
personal.unlockAccount(eth.coinbase);
var contractInstance = myContract.new({from: eth.coinbase, data: bytecode, gas: estimate + 50000});

记下 contractInstance.transactionHash 并挖矿确认:

miner.start(1);  // 单线程挖矿
// 等待数次出块
miner.stop();

// 确认结果
eth.getTransactionReceipt('上述 txHash').contractAddress

成功后即可调用:

var ticket = myContract.at('合约地址');
ticket.addTicket('Invoice-001', 'Content demo', {from: eth.accounts[0], gas: 200000});
ticket.getTicket.call(1);

多节点互连与持久化网络

1. 同一台机器启动两个节点

# 数据目录、端口均不冲突
geth --networkid 123 --datadir data2 --port 30304 --rpcport 8546 console

在新窗口查看本节点信息并邀请对端:

> admin.nodeInfo.enode
"enode://[email protected]:30304"
# 在另一个节点中执行:
admin.addPeer("enode://[email protected]:30304")

体验 net.peerCountadmin.peers 看连接状态。

2. 使用 genesis.json 初始化创世区块

创建 genesis.json

{
  "config": {
    "chainId": 2025,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
  },
  "alloc": {
    "0xbC9a3eCe02d7cb31Cf63DFDFc48dB0b82770d014": { "balance": "300000000000000000000" },
    "0x457e7D69FD3AC576aa744228e6B3319CDE768473": { "balance": "400000000000000000000" }
  },
  "difficulty": "0x20000",
  "gasLimit": "0x7A1200"
}

执行:

geth init genesis.json --datadir data-custom
geth --networkid 123 --datadir data-custom console

预置账户余额即刻生效,便于开发期免挖矿发交易。


FAQ:私有链实战常见疑惑

Q1:RPC 端口已开,外部仍连不上?
A:9090 以上端口可能受限于防火墙或安全组,确保云主机已放行对应 UDP/TCP,且 --rpcaddr 0.0.0.0 参数已启用。

Q2:estimateGas 返回的 gas 值为何总比实际小?
A:合约构造器或存储写入会额外消耗 gas,一般上浮 10%–20% 即可避免 out of gas。

Q3:Mist 无法显示合约函数?
A:合约版本需与 Mist 内置的 solidity 编译器一致;或直接在 Remix 切到“Injected Web3”方式远程调用。

Q4:想一键重置区块链怎么办?
A:删除 --datadir 指定的整个文件夹,重新 geth init 即清空全部历史,无需重新安装。

Q5:如何在同一局域网内让 A、B 两台电脑互通?
A:确保 --networkid 相同,A 把自己 enode://...@LAN_IP:PORT 通过 admin.addPeer 在 B 添加即可;若仍失败,检查路由是否屏蔽 30303/UDP。


进阶路径与资源延伸

到这里你已掌握:

👉 深挖更多以太坊私有链实战案例与调试技巧

接下来你可以:

  1. 将 Ganache 换成 Geth + PoA Clique,实现 5 秒出块。
  2. 使用 web3.js 在浏览器里发交易,前端直接调用私链。
  3. 引入 Docker 与 docker-compose,一条命令启动“节点 + 浏览器 + 后端”完整开发栈。

👉 24 小时内学会定制共识机制并迁移到私有链的完整图文教程


关键词:以太坊私有链、以太坊私网、geth 安装、智能合约部署、区块链 DApp 实战、创世区块配置