以太坊私有链搭建与智能合约部署指南
写在前面,图片实在是以md上传不了,实在不行你还是来github吧:https://github.com/williamtage5/Ethereum-Intranet-Chain-Building-and-Smart-Contract-Voting-Deployment-Guide
概念
-
CLI
CLI 是 Command Line Interface 的缩写,翻译过来就是命令行界面
-
RPC
RPC 是 Remote Procedure Call 的缩写,中文意思是“远程过程调用”。
在Web3和区块链的世界里,你可以把它理解成一个信使或者通信协议。
实际编写过程中,使用到的
web3.js
是一个能让你通过RPC与区块链进行交互的库。所以,简单来说,RPC就是让你的应用程序能够与以太坊区块链进行远程沟通的关键协议。
Step 1: 选择服务器
一般使用Linux系统。为了使用这个系统,偏向使用云服务器。
以AWS为例,可以使用EC2。
这里介绍一下EC2的含义:
EC2 是 Amazon Elastic Compute Cloud 的缩写 。它的名字本身就很好地解释了它的含义。我们可以把这个名字拆成两部分来理解:C2 - Compute Cloud (计算云)Cloud (云):意味着这个服务是运行在亚马逊遍布全球的巨大数据中心里的,而不是在你自己的电脑上 。Compute (计算):指的是这项服务的核心功能是提供计算能力,就像一台真实的电脑一样,它有处理器、内存、存储空间和操作系统,可以用来运行各种软件 。在手册里,它被明确描述为一项“在云端创建、管理和监控虚拟服务器”的服务 。E - Elastic (弹性的)这是EC2最特殊、最重要的含义。“弹性” 意味着你可以非常灵活地使用这些计算资源。你可以根据需要,在几分钟内就快速启动一台或多台虚拟服务器(在手册中这被称为“Launch instance”或“实例”) 。当你不再需要它时,也可以随时关掉并删除它,停止付费。这种像松紧带一样可以随时伸缩的能力,就是“弹性”的含义。
当然,你也可以使用阿里云、腾讯云、百度云或者其他的小厂商的服务器。
不管你选择何种服务器,你要进行如下设置:
- CPU几块都行
- ubuntu操作系统
- volumn 16 GB是安全的(但是我没有测试最少需要多少,但是8GB
是不行的,你可能会选择8GB的默认方案然后自己去扩充volumn)
像其他命名、开启连结密钥对这样的自己探究一下即可。
最终的目的是成功登录服务器的CLI,类似于下面:
Step 2: 安装环境
语言
像你在使用python搭建项目一样,你需要这样一门语言去告诉计算机如何操作。同样的,你需要告诉区块链组织的计算机如何操作完成你的任务,你就要有一个专门的语言或者说软件:Geth。
Geth 是 Go Ethereum 的简称。它是以太坊最主流的官方客户端软件,由Go语言开发。下载好这个,你就可以写符合这个语言规则的代码来告诉计算机你的需求。你所有以太坊的需求都要通过它传递。
可以实现的功能包括但不限于:
- 初始化区块链:使用 geth init 命令,根据你创建的 genesis.json 文件来“点燃”你自己的私有区块链网络 。
- 管理账户:通过 geth account new 命令来创建新的以太坊账户(钱包地址) 。
- 启动节点和交互:运行 Geth 会启动一个以太坊节点,并可以进入一个交互式的Javascript控制台 。在这个控制台里,你可以执行各种指令来操作你的区块链,比如查询余额、挖矿等。
那么,如何去安装Geth?
Step 2.1: 安装Go
安装Go语言是安装Geth的前提。
你需要按照如下步骤操作,下载、解压、移动特定版本的Go语言包:
-
cd ~
- 作用:切换到当前用户的“家目录”(Home Directory)。
- 解释:
cd
是change directory
(切换目录)的缩写。~
在Linux中是一个特殊符号,代表当前登录用户的个人主文件夹。这个命令确保你接下来的下载和解压操作都在一个干净、确定的位置进行。
-
wget https://storage.googleapis.com/golang/go1.21.6.linux-amd64.tar.gz
- 作用:从指定的网址下载Go语言的安装包。
- 解释:
wget
是一个从网络上下载文件的命令。后面的长链接就是Go语言特定版本(1.21.6)的下载地址。下载下来的是一个名为go1.21.6.linux-amd64.tar.gz
的压缩文件。
-
tar -xvf go1.21.6.linux-amd64.tar.gz
- 作用:解压缩刚刚下载的安装包。
- 解释:
.tar.gz
是一种常见的压缩格式,就像.zip
或.rar
文件一样。tar
命令就是用来处理这种格式的工具。-xvf
是它的参数,意思是“提取(extract)、显示过程(verbose)、从指定文件(file)”。执行后,你会得到一个名为go
的文件夹。
-
rm go1.21.6.linux-amd64.tar.gz
- 作用:删除已不再需要的压缩包。
- 解释:
rm
是remove
(移除)的缩写。既然已经成功解压出了go
文件夹,原来的那个压缩包就没用了。这个命令把它删除,以保持目录整洁。
-
sudo mv go /usr/local
- 作用:将解压出来的
go
文件夹移动到系统的标准程序安装位置。 - 解释:
mv
是move
(移动)的缩写。/usr/local
是Linux系统中一个用于安装软件的通用目录。sudo
是superuser do
的缩写,表示“以管理员权限执行”。因为/usr/local
是一个系统级目录,普通用户没有权限修改,所以必须加上sudo
。
- 作用:将解压出来的
总而言之,这五步操作就是一套标准的在Linux下手动安装软件的流程:进入家目录 → 下载压缩包 → 解压缩 → 删除压缩包 → 将程序移动到系统目录。完成之后,Go语言环境就成功安装到了你的EC2服务器上。
这时你可能你的console会有很多内容,会很卡,你可以刷新界面或者清除consoles上的内容。
已经下载好Go的包之后,操作系统还不知道。你需要去告诉它,这样你撰写go命令时操作系统才会知道去哪里去理解这个语言,这一步也被成为配置环境变量。你需要进行如下操作:
-
执行的命令:
sudo vim /etc/profile
- 这个命令的意思是:以管理员权限 (
sudo
) ,使用vim
这个文本编辑器 ,去打开并修改/etc/profile
这个系统配置文件 。
- 这个命令的意思是:以管理员权限 (
-
修改的文件:
/etc/profile
- 这是一个非常重要的系统级配置文件。当任何用户登录到这台Linux服务器时,系统都会自动执行这个文件里的命令,来为用户准备好工作环境。
-
为什么要做这件事?
- 在上一步,你把Go语言安装到了
/usr/local/go
目录下。但是,操作系统并不知道你把新软件装在了那里。 - 你可以把**“环境变量PATH”想象成是系统的一本“程序地址簿”**。当你输入一个命令(比如
go version
)时,系统就会翻阅这本地址簿,看看去哪里找这个叫go
的程序。 - 现在,Go的地址还没有登记在这本地址簿上。所以,你现在做的这一步,就是打开这本“地址簿” (
/etc/profile
文件),准备在里面添加一条新记录,告诉系统:“以后如果有人要用go
命令,就去/usr/local/go/bin
这个地方找。”
- 在上一步,你把Go语言安装到了
总而言之,这个步骤是在为刚刚安装的Go语言“注册登记”。如果不做这一步,系统就找不到Go程序,你就无法使用它来编译Geth,后续的实验也就无法进行了。
不知道Vim的uu可以看一下下面的简介:
"vim" is a powerful text editor in Linux. vim has two "modes": COMMANDmode and INSERT mode. Here are some basic vim commands to help you
get the most out of this editor:Start vim: Type "vim [filename]" in the terminal to open or create a file.press "gg" to move to the first line of the file.press "G" to move to the last line of the file.
Enter insert mode:i: Insert before the cursor.Exit vim: press "ESC" to enter COMMAND mode and type in below codes.:q Exit (if no changes).:q! Force exit without saving changes.:wq Save and exit
这样你打开了这个文件之后,按G将光标移动到最后,按i开启写入模式,然后把go的安装目录写进去:
-
第一行:
export GOPATH=/usr/local/go
export
: 这是一个声明命令,意思是将这个变量设置为“全局的”,让系统里所有的程序都能看到并使用它。GOPATH
: 这是Go语言专用的一个环境变量。你可以把它理解为Go语言的**“工作区”根目录**。它告诉Go相关的工具,你的Go项目和库都存放在哪里。/usr/local/go
: 这是你之前安装Go语言的路径。
简单来说,第一行代码的作用是: 定义一个名为
GOPATH
的变量,并告诉系统,Go语言的“大本营”就在/usr/local/go
这个位置。 -
第二行:
export PATH=$GOPATH/bin:$PATH
这一行是让系统能直接执行
go
命令的关键。export PATH=...
: 这里的PATH
是系统里最重要的环境变量,也就是我们之前比喻的“程序地址簿”。这行代码的作用就是要修改这个地址簿。$GOPATH/bin
:$GOPATH
会被替换成第一行里设定的值/usr/local/go
。所以,这部分就变成了/usr/local/go/bin
。这个/bin
目录是存放Go语言所有可执行命令(比如go
、gofmt
等)的地方。:
: 这是地址簿里的分隔符,用来隔开不同的路径。$PATH
: 这代表了“程序地址簿”里原来已经存在的所有路径。
简单来说,第二行代码的作用是: “请把Go语言的可执行程序目录 (
/usr/local/go/bin
),添加到系统现有程序地址簿 ($PATH
) 的最前面。”
这两行代码合在一起,完成了对Go语言环境的配置:
- 第一行指定了Go语言的工作目录。
- 第二行告诉了操作系统去哪里找Go的可执行命令。
完成这个配置并使其生效后,你就可以在终端的任何位置输入 go
命令,系统都能准确地找到并执行它。
写入完这两行意味着你的go语言的调用环境已经告诉了操作系统。这时你需要按esc,然后输入:wq,然后按回车,对修改的文件进行保存。
你安装好之后一般会想要测试一下是否安装成功。你可以:
source /etc/profile
go version
第一行:source /etc/profile
-
作用:让刚刚对
/etc/profile
文件的修改立即在当前的终端会话中生效。 -
为何要有这一行?
- 在之前的步骤中,你编辑并保存了
/etc/profile
这个系统配置文件,在里面添加了Go语言的路径信息。 - 但是,这个配置文件通常只在用户登录系统时才会自动加载一次。
- 你现在还处于之前的登录会话中,所以你做的修改对于当前的终端窗口来说,其实还“不存在”,系统并不知道你更新了“程序地址簿”。
source
命令的作用就是强制系统重新读取并执行一遍这个文件里的所有配置,就好像是按下一个“刷新”按钮。它让新的环境变量设置立刻生效,而无需退出登录再重新登录。
- 在之前的步骤中,你编辑并保存了
第二行:go version
-
作用:检查并显示当前安装的Go语言的版本号。
-
解释:
- 这一步是一个验证操作。它的目的是为了确认第一步
source /etc/profile
是否成功。 - 如果第一步成功了,那么系统现在应该已经知道了Go程序安装在哪里。此时执行
go version
,系统就能找到go
命令并成功输出版本信息(例如go version go1.21.6 linux/amd64
)。 - 如果系统返回“command not found”(找不到命令)之类的错误,那就说明环境变量没有配置成功。
- 这一步是一个验证操作。它的目的是为了确认第一步
这两行代码的关系是:
- 第一行
source /etc/profile
是“应用配置”:加载你新添加的Go语言路径。 - 第二行
go version
是“验证配置”:通过一个简单的Go命令来测试路径是否真的设置成功了。
会出现:
说明成功配置好Go的环境。
Step 2.2: 安装Geth
装好Go之后就可以装Geth了,主要分为四个步骤:下载源码、准备环境、编译构建、验证结果。
第一阶段:下载并解压源码
-
wget https://github.com/ethereum/go-ethereum/archive/refs/tags/v1.11.6.tar.gz
- 作用:从以太坊在GitHub上的官方代码仓库,下载 Geth 1.11.6 版本的源代码压缩包。
-
sudo tar -xvf v1.11.6.tar.gz
- 作用:解压缩刚刚下载的源码包。
-
rm v1.11.6.tar.gz
- 作用:删除源码压缩包,因为它已经没用了,这步是为了清理空间。
-
cd go-ethereum-1.11.6
- 作用:进入解压后得到的 Geth 源码目录,后续的编译操作都需要在这个目录里执行。
第二阶段:准备编译环境
-
sudo chmod -R 777 build/
- 作用:授予
build
文件夹最高的权限 。 - 解释:
chmod
是修改权限的命令。这样做是为了确保在接下来的编译过程中,系统不会因为权限不足而导致写入文件失败。
在`chmod`命令中,`777`是一个权限代码,代表着为文件或文件夹设置最高、最完全的访问权限。我们可以把这三个`7`拆开来看,每一个数字都对应着一类用户:1. 第一个 7:代表文件所有者 (Owner) 的权限。 2. 第二个 7:代表文件所属组 (Group) 的权限。 3. 第三个 7:代表其他所有人 (Others) 的权限。那么,数字`7`本身又是什么意思呢?它是由三种基本权限的数字代码相加得来的:* 读 (Read) 权限 = 4 * 写 (Write) 权限 = 2 * 执行 (Execute) 权限 = 1所以,一个数字`7`就意味着: 4 (读) + 2 (写) + 1 (执行) = 7 这表示**同时拥有读、写、执行这三种全部权限**。因此,`777`的完整含义就是: * 文件所有者:拥有“读、写、执行”权限 (第一个`7`)。 * 文件所属组:拥有“读、写、执行”权限 (第二个`7`)。 * 其他所有人:拥有“读、写、执行”权限 (第三个`7`)。在你的实验中,执行`sudo chmod -R 777 build/`,就是为了确保在编译Geth的过程中,系统中的任何用户和进程都有足够的权限去读取、写入和执行`build`目录下的任何文件,从而避免出现因权限不足导致的编译失败。
- 作用:授予
-
sudo apt update
- 作用:更新服务器的软件包列表。
- 解释:这个命令会连接到软件源,获取最新的可用软件包信息。这是安装新软件前的一个好习惯。
-
sudo apt install make
- 作用:安装
make
工具。 - 解释:
make
是一个非常重要的编译自动化工具。Geth 的源代码里包含一个Makefile
文件,该文件定义了如何一步步地将源代码转变为可执行程序。make
命令会读取这个文件并执行编译。
- 作用:安装
第三阶段:编译构建
-
make geth
- 作用:执行编译 。
- 解释:这是最核心的一步。
make
命令会根据Makefile
里的指示,调用我们之前安装好的 Go 语言编译器,开始将大量的.go
源代码文件编译、链接,最终生成一个名为geth
的可执行文件。如注释所说,这个过程会花费几分钟。
如何理解make好的,这是一个非常好的问题!这说明你已经开始思考底层原理了。我们用一个比喻来彻底讲清楚这一步。想象一下,你想做一道非常复杂的法式大餐。1. 源代码 vs. 可执行文件 (编译的意义)源代码 (Source Code):就是你下载的 `go-ethereum-1.11.6` 文件夹。它好比是这道法式大餐的“菜谱”。这份菜谱是用人类能看懂的语言(这里是Go语言)写成的,详细记录了每一步需要做什么。电脑 (CPU):你的电脑处理器,好比是一个只会执行“加热5分钟”、“搅拌30秒”这种最最基础指令的“厨房机器人”。它完全看不懂人类写的“菜谱”。可执行文件 (Executable File):这就是最终做好的、可以直接送进微波炉加热的“料理包”。它里面全是厨房机器人能直接理解的指令。所以,“编译”的意义就在于:请一位“大厨”(也就是**编译器**,这里是Go语言编译器),把人类看懂的“菜谱”(源代码),翻译并制作成一份“厨房机器人”能直接使用的“料理包”(可执行文件 `geth`)。没有编译这一步,你手里就只有一份菜谱,而没有能让电脑运行起来的程序。2. `make` 的意义现在,我们知道了需要一位“大厨”(编译器)来做菜。但 Geth 这道“法式大餐”太复杂了,菜谱有好几百页(几百个源代码文件),烹饪步骤有上千步。有些步骤必须按顺序来(先切菜才能炒菜)。有些步骤可以同时进行。有些步骤依赖于另一些步骤的完成品。如果你亲自指挥“大厨”一步一步地做,很容易出错,而且非常耗时。这时候,`make` 工具就出场了。`Makefile` 文件:在Geth的源代码(菜谱)里,附带了一张“总工序流程图”,它的名字就叫 `Makefile`。这张图由Geth的开发者们精心绘制,规定了编译Geth这道大餐的所有正确步骤和顺序。`make` 命令:你可以把 `make` 命令看作是一位非常聪明的“厨房总管”。当你执行 `make geth` 命令时,你其实是在对这位“厨房总管”说:“嘿,去看一下那张叫 `Makefile` 的总工序图,然后按照上面的指示,把名为 `geth` 的这道菜给我做出来!”这位“总管” (`make`) 就会自动地、高效地去指挥“大厨”(编译器)完成所有复杂的编译步骤。
第四阶段:验证结果
build/bin/geth version
- 作用:检查 Geth 是否编译成功。
- 解释:编译成功后,
geth
程序会被放在build/bin/
目录下。这条命令就是去运行这个新鲜出炉的程序,并让它打印出自己的版本信息。如果能成功看到版本号,就说明你已经从源代码成功构建了 Geth。
你进行完上述操作之后,你需要像配置Go路径一样,让计算机能够找到Geth的路径,你需要去配置它的系统路径。
首先去找到Linux的系统配置文件:
sudo vim /etc/profile
然后去将编译好的Geth的运行地址添加到系统的地址簿,让Geth运行的时候能够找到对应的支持文件进行运行。这样你就可以在任何目录下直接输入 geth
命令来运行它了。、
export PATH=$PATH:~/go-ethereum-1.11.6/build/bin
这是你要手动添加到文件末尾的核心代码。
export PATH=
: 声明要修改系统的PATH
变量(程序地址簿)。$PATH:
:$
符号表示引用变量的值。所以$PATH
代表“程序地址簿”里已经存在的所有路径,末尾的冒号:
是一个分隔符。~/go-ethereum-1.11.6/build/bin
: 这是 Geth 程序的新地址。~
代表你的用户主目录。go-ethereum-1.11.6
是你之前解压和编译 Geth 的文件夹。build/bin
是编译成功后,geth
这个可执行文件被存放的最终位置。
所以,整行代码的含义是:
“把我现有的程序地址簿 ($PATH
) 拿过来,然后在它的末尾加上 Geth 程序所在的目录 (~/go-ethereum-1.11.6/build/bin
),形成一份新的地址簿。”
如果不做这一步,每次你想运行Geth时,都必须输入它那长长的完整路径。而完成这一步之后,你就可以在任何地方简单地输入 geth
,系统都能根据这本更新后的“地址簿”找到并运行它。
同样的操作方法,G + i + 写入 + esc + :wq。
这样操作成功之后,你可以去验证是否安装成功。
source /etc/profile
geth version
如果没有问题,你应该看到下面的结果:
Step 3:开始部署链
Step 3.1: 设置专门的文件夹用于存放项目
这是一个良好的组织习惯,能让你的项目文件保持整洁。
-
cd ~
- 作用:切换到当前用户的个人主目录(Home Directory)。
- 解释:
cd
是change directory
(切换目录)的缩写。~
符号代表你的个人主文件夹。这步操作确保你从一个已知的基础位置开始,就像在电脑上先回到“我的文档”一样。
-
mkdir blockchain
- 作用:创建一个名为
blockchain
的新文件夹。 - 解释:
mkdir
是make directory
(创建目录)的缩写。这个新创建的blockchain
文件夹将作为你私有链的“家”,所有数据和配置文件都会放在这里。
- 作用:创建一个名为
-
cd blockchain
- 作用:进入刚刚创建的
blockchain
文件夹。 - 解释:执行这条命令后,你的命令行当前位置就在
blockchain
文件夹内部了。之后的所有操作(如创建创世文件)都将在这个目录里进行,以确保所有项目文件都集中在一起。
- 作用:进入刚刚创建的
Step 3.2: 手动创建创世区块(Genesis block)
我们已经安装好了Geth,我们可以调用Geth的语言来构建我们的第一个区块。
但是,更常用的做法是编写一个json文件,里面记录着一些配置。将这些配置传递给Geth后,Geth便能够运行我们的命令。
那么,问题就转化为编写json,然后传递给Geth。
Step 3.2.1 编写Json文件
创建一个json文件。
sudo vim ftec5520.json
写入必要的配置信息,前面一样的写入Linux文件的操作。内容例如:
{"config": {"chainId": 5520,"homesteadBlock": 0,"eip150Block": 0,"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000","eip155Block": 0,"eip158Block": 0,"byzantiumBlock": 0,"constantinopleBlock": 0,"petersburgBlock": 0,"ethash": {}},"nonce": "0x0000000000000042","mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000","difficulty": "10","alloc": {},"coinbase": "0x0000000000000000000000000000000000000000","timestamp": "0x0","parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000","extraData": "0x","gasLimit": "0xfffffff"
}