以太坊源码解析(一)

Posted by 姚飞亮 on 2020-07-09

以太坊源码解析(一)

项目地址:https://github.com/ethereum/go-ethereum

cd /Users/apple/Documents/app/go_project/src/github.com/ethereum/go-ethereum

项目构建

构建geth需要Go(1.13版或更高版本)和C编译器。您可以使用自己喜欢的软件包管理器来安装它们。

安装依赖项后,运行

1
make geth

或者,构建全套实用程序:

1
make all

go-ethereum项目随附在cmd 目录中找到的几个包装器/可执行文件。

命令 描述
geth 我们主要的以太坊CLI客户端。它是以太坊网络(主,测试或私有网络)的入口点,可以作为完整节点(默认),存档节点(保留所有历史状态)或轻节点(实时获取数据)运行。其他进程可以通过暴露在HTTP,WebSocket和/或IPC传输之上的JSON RPC终结点,将其用作进入以太坊网络的网关。geth --help以及命令行选项的CLI Wiki页面
abigen 源代码生成器,用于将以太坊合同定义转换为易于使用的,编译时类型安全的Go软件包。如果还提供了合约字节码,它可以在具有扩展功能的普通以太坊合约ABI上运行。但是,它也接受Solidity源文件,从而使开发更加简化。有关详细信息,请参见我们的Native DApps Wiki页面。
bootnode 我们的以太坊客户端实现的精简版本,仅参与网络节点发现协议,但不运行任何更高级别的应用程序协议。它可用作轻型引导节点,以帮助在专用网络中查找对等节点。
evm EVM(以太坊虚拟机)的开发人员实用程序版本,能够在可配置的环境和执行模式下运行字节码摘要。其目的是允许对EVM操作码(例如evm --code 60ff60ff --debug run)进行隔离的细粒度调试。
gethrpctest 开发人员实用工具,用于支持我们的以太坊/ rpc-test测试套件,该套件可验证与以太坊JSON RPC规范的基准一致性。有关详细信息,请参阅测试套件的自述文件
rlpdump 开发人员实用程序工具,用于将二进制RLP(递归长度前缀)转储(以太坊协议使用的数据编码,无论是网络还是共识方式)转换为用户友好的层次表示形式(例如rlpdump --hex CE0183FFFFFFC4C304050583616263)。
puppeth 一个CLI向导,可帮助创建新的以太坊网络。

太坊CLI客户端 geth

以太坊主网络上的完整节点

最常见的情况是人们只想与以太坊网络进行交互:创建帐户;转移资金; 部署合同并与之交互。对于这种特定的用例,用户无需关心已有多年的历史数据,因此我们可以快速快速同步到网络的当前状态。

1
2
# 以太坊主网络上的完整节点
geth console

该命令将:

  • geth以快速同步模式启动(默认情况下,可以用该--syncmode标志更改),从而使其下载更多数据作为交换,从而避免处理以太坊网络的整个历史记录,这是占用大量CPU的资源。
  • 启动geth内置的交互式JavaScript控制台(通过结尾的console子命令),您可以通过该控制台调用所有官方web3方法 以及geth自己的管理API。该工具是可选的,如果不使用它,则可以始终使用附加到已在运行的 geth实例geth attach

–goerli测试网络

1
2
$ geth --goerli console
# --goerli 客户端将连接到goerli测试网络

与其使用默认的数据目录(~/.ethereum例如,在Linux上),geth 不如将其自身嵌套更深一层到goerli子文件夹(~/.ethereum/goerli在Linux上)。请注意,在OSX和Linux上,这还意味着附加到运行中的testnet节点需要使用自定义端点,因为geth attach默认情况下它将尝试附加到生产节点端点 geth attach /goerli/geth.ipc。Windows用户不受此影响。

–rinkeby测试网络

Go Ethereum还支持连接到称为Rinkeby的较早的基于权威证明的测试网络,该网络由社区成员运营

1
$ geth --rinkeby console

–ropsten测试网络

除了Görli和Rinkeby,Geth还支持古老的Ropsten测试网。Ropsten测试网络基于Ethash工作量证明共识算法。这样,它具有一定的额外开销,并且由于网络的低难度/安全性而更容易受到重组攻击的影响。

注意:较旧的Geth配置将Ropsten数据库存储在testnet子目录中。

1
$ geth --ropsten console

配置

除了将大量标志传递给geth二进制文件之外,还可以通过以下方式传递配置文件

1
$ geth --config /path/to/your_config.toml

要了解文件的外观,可以使用dumpconfig子命令导出现有配置:

1
$ geth --your-favourite-flags dumpconfig

注意:这仅适用于gethv1.6.0及更高版本。

Docker快速入门

在机器上启动并运行以太坊的最快方法之一是使用Docker:

1
2
3
docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
-p 8545:8545 -p 30303:30303 \
ethereum/client-go

geth就像上面的命令一样,它将以1GB的DB内存配额在快速同步模式下启动。它还将在您的主目录中创建一个持久卷,以保存您的区块链并映射默认端口。还有一个alpine标签可用于图像的精简版。

--rpcaddr 0.0.0.0如果您想从其他容器和/或主机访问RPC,请不要忘记。默认情况下,geth绑定到本地接口,并且无法从外部访问RPC端点。

以编程方式接口geth节点

作为一名开发人员,您希望早晚geth通过您自己的程序而不是通过控制台手动与以太坊网络进行交互。为此,geth内置支持基于JSON-RPC的API(标准APIgeth特定API)。这些可以通过HTTP,WebSocket和IPC(在基于UNIX的平台上为UNIX套接字,在Windows上为命名管道)公开。

IPC接口默认情况下处于启用状态,并且公开了所支持的所有API geth,而出于安全原因,HTTP和WS接口需要手动启用,并且仅公开一部分API。可以按照您的期望打开/关闭和配置它们。

基于HTTP的JSON-RPC API选项:

  • --rpc 启用HTTP-RPC服务器
  • --rpcaddrHTTP-RPC服务器侦听端口(默认:localhost
  • --rpcportHTTP-RPC服务器侦听端口(默认值:8545
  • --rpcapiAPI的通过HTTP-RPC接口提供的(默认:eth,net,web3
  • --rpccorsdomain 逗号分隔的域列表,从中接受跨域请求(强制浏览器)
  • --ws 启用WS-RPC服务器
  • --wsaddrWS-RPC服务器侦听端口(默认:localhost
  • --wsportWS-RPC服务器侦听端口(默认值:8546
  • --wsapiAPI的在WS-RPC接口提供的(默认:eth,net,web3
  • --wsorigins 接受网络套接字请求的来源
  • --ipcdisable 禁用IPC-RPC服务器
  • --ipcapiAPI的在IPC-RPC接口提供的(默认:admin,debug,eth,miner,net,personal,shh,txpool,web3
  • --ipcpath datadir中IPC套接字/管道的文件名(显式路径对其进行转义)

您将需要使用自己的编程环境的功能(库,工具等)通过HTTP,WS或IPC连接到geth配置有上述标志的节点,并且需要在所有传输方式上使用JSON-RPC。您可以将同一连接重用于多个请求!

注意:在执行此操作之前,请了解打开基于HTTP / WS的传输的安全性!互联网上的黑客正在积极尝试使用公开的API来破坏以太坊节点!此外,所有浏览器选项卡都可以访问本地运行的Web服务器,因此恶意网页可能试图破坏本地可用的API!

运营私人网络

维护您自己的专用网络会更加繁琐,因为需要手动设置许多在官方网络中理所当然的配置。

定义私人起源状态

首先,您需要创建网络的起源状态,所有节点都需要了解并达成共识。这由一个小的JSON文件(例如称为genesis.json)组成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"config": {
"chainId": <arbitrary positive integer>,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}

尽管我们建议将更nonce改为一些随机值,但上述字段对于大多数用途还是不错的,这样可以防止未知的远程节点能够连接到您。如果您想为一些帐户预先注资以进行更轻松的测试,请创建帐户并在其alloc字段中填充其地址。

1
2
3
4
5
6
7
8
"alloc": {
"0x0000000000000000000000000000000000000001": {
"balance": "111111111"
},
"0x0000000000000000000000000000000000000002": {
"balance": "222222222"
}
}

使用上述JSON文件中定义的创始状态,您需要在启动每个 geth节点之前对其进行初始化,以确保正确设置所有区块链参数:

1
$ geth init path/to/genesis.json

创建集合点

将要运行的所有节点初始化为所需的创始状态后,您需要启动一个引导节点,其他节点可以使用该节点在网络和/或Internet上相互查找。干净的方法是配置并运行专用的引导节点:

1
2
$ bootnode --genkey = boot.key 
$ bootnode --nodekey = boot.key

引导节点在线时,它将显示一个enodeURL ,其他节点可以使用该URL连接到该节点并交换对等信息。确保[::]使用外部可访问的IP 替换显示的IP地址信息(最有可能是),以获取实际的enodeURL。

注意:您也可以将成熟的geth节点用作引导节点,但这是不建议使用的方法。

启动您的成员节点

在bootnode可操作且在外部可访问(您可以尝试 telnet确保它确实可访问)的情况下,启动所有geth 指向该bootnode的后续节点,以通过该--bootnodes标志进行对等发现。最好将私有网络的数据目录分开,因此也要指定一个自定义--datadir标志。

1
$ geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>

注意:由于您的网络将与主网络和测试网络完全断开,因此您还需要配置一个矿工来处理交易并为您创建新的区块。

经营私人矿工

在以太坊公共网络上进行挖掘是一项复杂的任务,因为只有在使用GPU(需要启用OpenCL或CUDA的ethminer实例)时才可行。有关此类设置的信息,请查阅EtherMining subredditethminer存储库。

但是,在专用网络设置中,单个CPU矿工实例对于实际目的来说绰绰有余,因为它可以按正确的时间间隔生成稳定的块流,而无需占用大量资源(考虑在单个线程上运行,也不需要多个线程) )。要启动geth实例进行挖掘,请使用所有常规标志运行它,并扩展为:

1
$ geth <usual-flags> --mine --miner.threads=1 --etherbase=0x0000000000000000000000000000000000000000

它将在单个CPU线程上开始挖掘块和事务,并将所有过程记入所指定的帐户--etherbase。您可以通过将默认的气体限制块收敛到(--targetgaslimit)来进一步调整采矿,并在(--gasprice)接受价格交易。



Ω