区块链:搭建简单以太坊Geth私有链
在Geth环境下,搭建一个私有测试链,并掌握以太坊的基本命令。
Fabric搭建教程:搭建简单Fabric网络
【重要免责声明与阅读须知】
-
环境隔离性:文中涉及的所有实验操作均在本地私有测试链或专门测试网(如Goerli、Sepolia) 上完成。严禁在任何主网(Mainnet)或公有链环境下尝试任何攻击行为。
-
风险自担:读者应确保在完全隔离、无真实资产的实验环境中进行学习。因违反此须知而造成的任何资产损失,作者概不负责。
-
合规性:请严格遵守您所在国家或地区的法律法规。区块链技术本身中立,但使用方式决定其性质。
目录
背景知识
以太坊(Ethereum)
一个开源、去中心化的区块链平台和生态系统,定义了一套协议规则(EVM),包括加密货币 ETH、数以万计的智能合约、去中心化应用。
Geth (Go Ethereum)是用以太坊协议规则写成的、最流行的官方客户端软件之一,提供了一个接口与以太坊网络交互,由 Go 语言编写。
节点
以太坊是⼀个由计算机组成的分布式⽹络,这些计算机运⾏可验证区块和交易数据的软件,称为节点。 软件应⽤程序(客户端)必须在电脑上运⾏,将你的电脑变成⼀个以太坊节点。(简单理解:⼀个节点就是⽹络上的⼀个运⾏以太坊的电脑)
所有节点在搭建之前都需要初始化创世区块(genesis.json),作为区块链的起点,定义初始状态和网络规则,⽂件夹中保存了这个节点的全部信息,需要运⾏才能启动⼀个节点,节点重启信息不丢失。 想要相互连接,节点的 networkid 要⼀致
账户(Account)
以太坊则采⽤账户来记录系统状态。每个账户存储余额信息、智能合约代码和内部数据存储等。以太坊⽀持在不同的账户之间转移数据,以实现更为复杂的逻辑。
以太坊账户分为两种类型:合约账户(Contracts Accounts)和外部账户(Externally Owned Accounts, EOA)。
合约账户:存储执⾏的智能合约代码,只能被外部账户来调⽤激活;
外部账户:以太币拥有者账户,由私钥控制,包括 nonce、balance、storageRoot、
codeHash 等字段。
当合约账户被调⽤时,存储其中的智能合约会在矿⼯处的虚拟机中⾃动执⾏,并消耗⼀定的燃料(Gas),燃料通过外部账户用以太币(Ether)支付。
交易 (Transaction)
在以太坊中是指从⼀个账户到另⼀个账户的消息数据。消息数据可以是以 太币或者合约执⾏参数,以太坊采⽤交易作为执⾏操作的最⼩单位。每个交易包括如下字段:
to:⽬标账户地址。
value:可以指定转移的以太币数量。
nonce:交易相关的字串,⽤于防⽌交易被重放。
gasPrice:执⾏交易需要消耗的 Gas 价格。
gasLimit:交易消耗的最⼤ Gas 值。
data: 交易附带字节码信息,可⽤于创建/调⽤智能合约。
signature:基于椭圆曲线加密的签名信息,包括R,S,V 三个字段。
类似⽐特币⽹络,在发送交易时,⽤户需要缴纳⼀定的交易费⽤,通过以太币(Ether)⽅式进⾏⽀付 、消耗,以太币最⼩单位是 wei,⼀个以太币等于 10^18 个 wei。
实验目的
- 搭建一个以太坊的多节点私有网络;
- 在以太坊的架构下如何去编写、调用智能合约,并设计代码来复现重入漏洞攻击。
实验环境
- Ubuntu 20.04的VMware虚拟机
- Go语言版本1.18.5
- 在线合约编译工具Remix
- 谷歌浏览器(建议)
安装Geth
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum
写入配置文件~/.bashrc,替换用户名:
export GETH=/home/lo/go-ethereum
export PATH=$PATH:$GETH/build/bin

安装Golang
(若上一篇装过可跳过)
# 下载官⽹的linux x86-64 Archive
wget https://golang.google.cn/dl/go1.19.3.linux-amd64.tar.gz --no-check-certificate
# 解压
sudo tar -xzf go1.19.3.linux-amd64.tar.gz -C /usr/local
# 主⽬录下建⽴goDir⽂件夹,做为GOPATH路径
mkdir ~/goDir
# 在zsh配置⽂件中添加系统PATH
vim ~/.zshrc
export GOPATH=/home/seed/goDir
export GOROOT=/usr/local/go
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
# 刷新配置⽂件
source ~/.zshrc
# 让root也能执⾏go命令(如果root没有安装zsh,则修改 /root/.bashrc)
sudo su
vim ~/.zshrc
export GOPATH=/home/seed/goDir
export GOROOT=/usr/local/go
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
# 验证安装
go version
geth version
以太坊私有链搭建
搭建区块:
cd ~/blockchain
mkdir ethereum
cd ~/blockchain/ethereum
# 按照上⾯的genesis.json创建
vim genesis.json
# 初始化创世区块,注意所有节点在搭建之前都需要初始化创世区块
geth --datadir data0 init genesis.json
后续智能合约若要连接到该私有链,需要在启动私有链节点时指定:
--http :将允许对于节点的http连接,以便后续使⽤Remix⼯具连接本地私有链
--allow-insecure-unlock :允许解锁账户(进⾏转账等操作需要解锁账户)
console :将直接进⼊节点的命令⾏
--http.corsdomain https://remix.ethereum.org :后续连接到remix则添加,不然可以删除
geth --http --http.corsdomain https://remix.ethereum.org --datadir data0 --networkid 1108 console --allow-insecure-unlock
创世区块genesis.json
- "difficulty"设置的很低,挖矿速度很快
- "gasLimit"必须要⾼,否则会因为gas太⼩,不给你交易
- "chainId"与以太坊⽹络相对应
{
"config" : {
"eip150Block" : 0,
"petersburgBlock" : 0,
"byzantiumBlock" : 0,
"istanbulBlock" : 0,
"eip155Block" : 0,
"eip158Block" : 0,
"homesteadBlock" : 0,
"chainId" : 666666,
"constantinopleBlock" : 0
},
"timestamp" : "0x00",
"extraData" : "0x00",
"alloc" : {
"0x3Ecb2d7d3622d8FB030330D2c284dF77DE50d303" : {
"balance" : "9000000000000000000000000000"
}
},
"difficulty" : "0x1",
"gasLimit" : "0x80000000",
"parentHash" :
"0x0000000000000000000000000000000000000000000000000000000000000000",
"mixhash" :
"0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x0000000000000000000000000000000000000000",
"nonce" : "0x0000000000000042"
}

账户操作
另开⼀个终端,进⼊data0⽂件夹,连接⾄该节点的命令⾏:
cd data0
geth attach ipc:geth.ipc
# 连接⾄该节点的命令⾏
# 添加⼀个账户
personal.newAccount()
# 查看所有账户
eth.accounts
# 解锁第⼀个账户
acc0 = eth.accounts[0]
personal.unlockAccount(acc0)
# 锁定第⼀个账户
personal.lockAccount(acc0)
# 查看某账户的余额,返回值的单位是 Wei,1 ether = 10^18 Wei
eth.getBalance(acc0)
# 列出区块总数(忽略了创世区块)
eth.blockNumber
# 获取区块信息,输⼊区块编号
eth.getBlock(1)
# 开始计算(需要⾄少有⼀个账户)
# 如果genesis.json中没有指定收益账户,则挖矿所得到的收益归 eth.accounts[0]
miner.start()
# 停⽌
miner.stop()
在data0下创建账户:



转账操作
转账本质上就是发起一笔交易(Transaction),该交易的核心是从一个账户向另一个账户发送一定数量的 ETH(以太币),在私有链中,发送交易只是第一步。交易必须被矿工打包进区块才算最终确认。
这个过程涉及以下关键点:
-
发送者 (From):必须是一个外部账户 (EOA),即由私钥控制的账户。合约账户不能主动发起交易。
-
接收者 (To):可以是一个外部账户,也可以是一个合约账户。
-
Gas:执行交易需要消耗的计算资源,需要支付少量 ETH 作为手续费。即使在私有链中,这个机制依然存在。
-
Nonce:每个账户独有的交易计数器,用于防止重放攻击。
# 转账(有钱才能转账!)
# 转账后需要等⼀段时间后才能看⻅(要有矿⼯在挖矿才⾏)
# 账号0给账号1转 20 ether
personal.newAccount()
acc0 = eth.accounts[0]
acc1 = eth.accounts[1]
personal.unlockAccount(acc0)
eth.sendTransaction({from:acc0,to:acc1,value:web3.toWei(20)})
# 后续要⽤到新创建的acc1和acc2
# 账号0给账号2转 20 ether
personal.newAccount()
acc0 = eth.accounts[0]
acc2 = eth.accounts[2]
personal.unlockAccount(acc0)
eth.sendTransaction({from:acc0,to:acc2,value:web3.toWei(20)})
# Wei 换算成以太币
web3.fromWei()
# 以太币换算成 Wei
web3.toWei()
# 交易池中的状态,转账中还没有被区块记录的信息。
txpool.status
解锁账号后查询余额,相互转账,查看账户余额:


更多推荐
所有评论(0)