以太坊源码解析(七)Geth开发

Posted by 姚飞亮 on 2020-07-11

以太坊源码解析(七)Geth开发

开发人员指南

注意:这些说明适用于希望贡献Go源代码更改的人员。如果您只想运行以太坊,请使用常规的安装说明

本文档是以太坊的Go实施开发人员的切入点。这里的开发人员可以参考动手实践:对构建,开发,调试,提交错误报告或请求请求或向以太坊贡献代码感兴趣的人员。

贡献

感谢您考虑提供源代码帮助!我们欢迎互联网上任何人的贡献,并感谢即使是最小的修复!

GitHub用于跟踪问题并提供代码,建议,功能请求或文档。

如果您想为以太坊做贡献,请分叉,修复,提交并发送拉取请求(PR),以供维护者查看并合并到主要代码库中。如果您希望提交更复杂的更改,请与go-ethereum Discord Server中的核心开发人员联系。确保这些更改符合项目的总体理念和/或获得一些早期反馈。这样可以减少您的工作量,并加快我们的审核和合并过程。

PR需要基于master分支并针对该分支开放(除非达成明确协议,否则您将贡献一个复杂的功能分支)。

您的PR将根据《准则审查》指南进行审查。

我们鼓励采用PR的早期方法,这意味着即使没有修复/功能,您也可以尽早创建PR。这将使核心开发人员和其他志愿者知道您遇到了问题。这些早期PR应当指示“进行中”状态。

建造和测试

我们假设您已经安装了Go。请使用Go版本1.13或更高版本。我们使用gc工具链进行开发,您可以从Go下载页面获得该工具链。

go-ethereum是一个Go模块,并使用Go模块系统来管理依赖项。GOPATH不需要使用来构建以太坊。

建筑可执行文件

切换到以太坊存储库根目录。

您可以使用go工具构建所有代码,并将生成的二进制文件放入中$GOPATH/bin

1
go install -v ./...

go-ethereum可执行文件可以单独构建。要构建geth,请使用:

1
go install -v ./cmd/geth

如果要为不同于主机的体系结构编译geth,请查阅我们的交叉编译指南

测试中

测试包:

1
go test -v ./eth

运行单个测试:

1
go test -v ./eth -run TestMethod

注意:此处将运行所有带有前缀TestMethod的测试,因此,如果您获得TestMethod,TestMethod1,则两个测试都将运行。

运行基准测试,例如:

1
go test -v -bench . -run BenchmarkJoin

有关更多信息,请参阅go test flags文档。

获取堆栈跟踪

如果geth使用该--pprof选项启动,则会在端口6060上提供调试HTTP服务器。您可以打开http:// localhost:6060 / debug / pprof来查看堆,正在运行的例程等。单击“完整的goroutine堆栈转储”您可以生成对调试有用的跟踪。

请注意,如果您运行的多个实例geth,则此端口仅适用于已启动的第一个实例。如果要为这些其他实例生成堆栈跟踪,则需要选择其他pprof端口来启动它们。确保将stderr重定向到日志文件。

1
2
3
geth -port=30300 -verbosity 5 --pprof --pprofport 6060 2>> /tmp/00.glog
geth -port=30301 -verbosity 5 --pprof --pprofport 6061 2>> /tmp/01.glog
geth -port=30302 -verbosity 5 --pprof --pprofport 6062 2>> /tmp/02.glog

或者,如果您想杀死客户机(以防客户机挂起或停止同步等)并具有堆栈跟踪,则可以将-QUIT信号与kill以下命令一起使用:

1
killall -QUIT geth

这会将每个实例的堆栈跟踪信息转储到它们各自的日志文件中。

代码审查准则

使代码进入以太坊的唯一方法是发送请求请求。这些拉取请求需要由某人进行审核。本文档是一份指南,解释了我们对作者和审稿人对PR的期望。

术语

  • 拉取请求的作者是编写差异并将其提交到GitHub的实体。
  • 团队由在以太坊存储库中具有提交权限的人员组成。
  • 评审是分配给审查差异的人。审阅者必须是团队成员。
  • 代码所有者负责通过公关修改子系统之中的人。

流程

进行任何PR的第一个决定是是否值得包括所有PR。该决定主要由代码所有者决定,但可以与团队成员协商。

要做出决定,我们必须了解PR的含义。如果描述内容不足或差异太大,请请求解释。任何人都可以做这部分。

我们希望审阅者检查PR的样式和功能,并使用GitHub审阅系统向作者提供评论。审阅者应跟进PR,直到其状态良好,然后批准 PR。批准的PR可以由任何代码所有者合并。

与作者交流时,要礼貌和尊重。

代码风格

我们期待gofmted代码。对于大量的贡献,我们希望作者能够理解和使用Effective Go中的指南。作者应避免在Go Code Review Comments页面中解释的常见错误。

功能检查

对于可解决问题的PR,审阅者应尝试重现该问题并验证拉取请求是否已解决。作者可以通过包含在没有更改(并通过更改)的情况下失败的单元测试来帮助实现这一点。

对于添加新功能的PR,审阅者应尝试使用该功能并评论使用它的感觉。示例:如果PR添加了新的命令行标志,请将该程序与该标志一起使用并评论该标志是否有用。

我们期望适当的单元测试范围。审阅者应验证新代码是否包含在单元测试中。

CI

提交的代码必须通过所有单元测试和静态分析(“棉绒”)检查。我们使用Travis CI在Linux,macOS和AppVeyor上测试代码在Microsoft Windows上测试代码。

对于失败的CI构建,问题可能与PR本身无关。这种故障通常与火焰测试有关。这些失败可以忽略(作者不需要修复无关的问题),但是请提交GH问题,以便最终修复测试。

提交讯息

master分支上的提交消息应遵循以下规则。PR作者不需要使用任何特定样式,因为可以在合并时修改消息。强制实施提交消息样式是合并PR的人员的责任。

我们使用的提交消息样式类似于Go项目使用的样式:

变更描述的第一行通常是变更的单行摘要,以受影响的主要Go软件包为前缀。它应完成以下语句:“此更改将以太坊修改为_。” 本说明的其余部分将详细阐述,并应提供有关更改的上下文并解释更改的作用。

模板:

1
2
3
4
5
6
7
package/path: change XYZ

Longer explanation of the change in the commit. You can use
multiple sentences here. It's usually best to include content
from the PR description in the final commit message.

issue notices, e.g. "Fixes #42353".

特殊情况以及如何处理

作为审阅者,您可能会发现自己处于以下情况之一。解决这些问题的方法如下:

  • 作者没有采取后续行动:过一会儿(即几天后)ping它们。如果没有其他响应,请关闭PR或自行完成工作。
  • 作者坚持将重构更改与错误修复一起进行:我们可以容忍任何改动的情况下进行小的重构。如果您对差异感到迷惑,请要求作者将重构作为独立的PR提交,或至少作为同一PR中的独立提交提交。
  • 作者不断拒绝您的反馈:审稿人有权出于技术原因拒绝任何更改。如果您不确定,请向团队征求其他意见。如果无法达成共识,则可以关闭PR。

问题处理工作流程

(提案草案)

将未解决问题的数量保持在820以下

将所有未解决问题的比例保持在13%以下

有50期标记为想要帮助,50期为良好的第一期

使用结构形式的标签,例如,:如果需要的话。:/`area: plugins/foobuzzer`

使用以下标签。区域和状态取决于应用程序和工作流程。

    • area: android
    • area: clef
    • area: network
    • area: swarm
    • area: whisper
  • 类型
    • type: bug
    • type: feature
    • type: documentation
    • type: discussion
  • 状态
    • status: PR review
    • status: community working on it
  • 需要
    • need: more info
    • need: steps to reproduce
    • need: investigation
    • need: decision

使用这些里程碑

  • 未来 -也许会实施一天
  • 即将推出 -未分配给特定版本,但将在即将发布的版本中提供
  • <下一个版本>-具有版本号的下一发行版
  • <下一个下一个版本>-下一个发行版之后的版本,带有版本号
  • <下一个主要版本>-可选。

可以不设置里程碑的截止日期是可以的,但是一旦发布里程碑,请关闭它。如果有一些悬而未决的问题,请考虑将其移至下一个里程碑,然后关闭该里程碑。

(可选)使用项目委员会来收集具有最终状态并覆盖多个发行版的较大工作量的问题。

工作流程

我们每周或每两周进行一次分类会议。通过问题标记为“ status:triage”来预先选择问题,然后对最早的问题进行排序。这是当我们经历新问题并执行以下操作之一时

  1. 关闭它。
  2. 将其分配给没有结束日期的“即将到来”里程碑。
  3. 将其移至“未来”里程碑。
  4. 将其状态更改为“需要:<需要什么>”。

可选的其他活动:

  • 用适当的区域/组件标记问题。
  • 在“常见问题解答”中添加一个部分或添加一个维基页面。从问题链接到它。

DNS发现设置指南

本文档说明了如何使用devp2p开发人员工具设置EIP 1459节点列表。本指南的重点是为以太坊主网和公共测试网创建公共列表,但是如果您想为专用网络设置基于DNS的发现,则也可能会有所帮助。

当与发现DHT的连接不可用时,基于DNS的节点列表可以用作后备选项。在本指南中,我们将通过搜寻发现DHT来创建节点列表,然后在选定的DNS名称下发布结果节点集。

安装devp2p命令

cmd / devp2p是开发人员实用程序,没有包含在Geth发行版中。您可以使用以下命令安装此命令go get

1
go get -u github.com/ethereum/go-ethereum/cmd/devp2p

要创建签名密钥,您可能还需要该ethkey实用程序。

1
go get -u github.com/ethereum/go-ethereum/cmd/ethkey

搜寻v4 DHT

我们的第一步是编译所有可到达节点的列表。cmd / devp2p中的DHT搜寻器是一个批处理过程,运行一定时间。您应该安排此命令定期运行。要创建节点列表,请运行

1
devp2p discv4 crawl -timeout 30m all-nodes.json

这将遍历DHT,并将所有找到的节点的集合存储在all-nodes.json文件中。随后运行同一命令将重新验证先前发现的节点记录,将新发现的节点添加到集合中,并删除不再活动的节点。每次运行都会提高节点集的质量,因为重新验证的次数会与该集中的每个节点一起跟踪。

通过过滤创建子列表

一旦all-nodes.json已经创建和该组中包含的节点的一个相当大的数量,可以使用被提取的节点的有用的子集devp2p nodeset filter的命令。该命令将节点集文件作为参数,并应用作为命令行标志给出的过滤器。

要创建过滤的节点集,请首先创建一个新目录来保存输出集。您可以使用任何目录名称,尽管将DNS域名用作此目录的名称是一种很好的做法。

1
mkdir mainnet.nodes.example.org

然后,要创建仅包含以太坊主网节点的输出集,请运行

1
devp2p nodeset filter all-nodes.json -eth-network mainnet > mainnet.nodes.example.org/nodes.json

以下过滤器标志可用:

  • -eth-network ( mainnet | ropsten | rinkeby | goerli ) 选择一个以太坊网络。
  • -les-server 选择LES服务器节点。
  • -ip 将节点限制为给定的IP范围。
  • -min-age 将结果限制为在给定持续时间内处于活动状态的节点。

创建DNS树

要将节点列表转换为DNS节点树,需要对列表进行签名。为此,您需要一个密钥对。要以正确的格式创建密钥文件,可以使用cmd / ethkey实用程序。请选择一个好的密码来加密磁盘上的密钥。

1
ethkey generate dnskey.json

现在用于devp2p dns sign更新节点列表的签名。如果列表的目录名称与您要发布的目录名称不同,请使用-domain标志指定DNS名称。此命令将提示您输入密钥文件密码并更新树签名。

1
devp2p dns sign mainnet.nodes.example.org dnskey.json

生成的DNS树元数据存储在 mainnet.nodes.example.org/enrtree-info.json文件中。

发布DNS树

现在树已签名,可以将其发布到DNS提供程序。cmd / devp2p当前支持发布到CloudFlare DNS和Amazon Route53。您还可以将TXT记录导出为JSON文件,然后自己发布。

要发布到CloudFlare,请首先在管理控制台中创建一个API令牌。cmd / devp2p需要CLOUDFLARE_API_TOKEN环境变量中的API令牌。现在,使用以下命令通过CloudFlare API上传DNS TXT记录:

1
devp2p dns to-cloudflare mainnet.nodes.example.org

请注意,此命令使用签名期间指定的域名。此名称下的所有现有记录将被cmd / devp2p擦除。

在Geth中使用DNS树

一旦树通过DNS名称可用,就可以告诉geth将其与 --discovery.dns命令行标志一起使用。节点树是使用enrtree://URL方案引用的。您可以在enrtree-info.json创建的文件中 找到树的URL devp2p dns sign。只需将URL作为参数传递给标志,以利用已发布的树。

1
geth --discovery.dns "enrtree://AMBMWDM3J6UY3M32TMMROUNLX6Y3YTLVC3DC6HN2AVG5NHNSAXDW6@mainnet.nodes.example.org"


Ω