重走长征路·geth以太坊源代码再解读

重走长征路·geth以太坊源代码再解读,第1张

背景

geth是以太坊官方的golang版本的客户端,代码简洁,结构精妙,是学习golang的好素材。
第一次读geth代码,是2017年,在连连数字研究院时候,带着对go的零基础,带着区块链之热,看得比较支离破碎。
而今4年过去,工作地方从杭州、上海,到了南洋新加坡。重读geth,一是了解geth最新进展,二是也加深对golang的理解,因为现在工作正好用到golang。
想起来了一首词,可以作为当前心境的一种注解。

少年听雨歌楼上,红烛昏罗帐。
壮年听雨客舟中,江阔云低,断雁叫西风。
而今听雨僧庐下,鬓已星星也。
悲欢离合总无情,一任阶前点滴到天明。

重读评论:

比如 geth源码解读1:p2p通讯.md

1. 选了一个好的切入点,因为geth神奇的第一步就是去中心化,带来的问题是怎么找到网络环境差别很大的其他节点?

这个技术互联网用不上,但是对p2p客户端很重要 互联网模式不同,服务器-客户端模式,服务器不需要反向主动连客户端
从这点看技术视角很重要,读代码要有一个好的切入点。

2. 初读的问题是对golang还不熟悉,看某个模块,有点“蜻蜓点水”,自己心中还没有模式,所以看代码有点支离破碎,“见木不见林”

还是p2p为例子,其实现在go代码写多了,知道最重要先看interface,在看不同struct对其实现,思考为什么要这样抽象

nat,geth客户端扮演了upnp的客户端,发出通用的协议,在家用路由器上可以看到注册的upnp端口(也就是在路由器统一ip地址上开了端口,打了个洞)
p2p包-》nat子包

以上我论述存在偏差,因为只看到了upnp,其实节点情况还有ExtIP,还有pmp

3. 快速读代码能力

其实nat包下面代码文件不多,现在我知道了,先筛掉test文件,在看命名最简短的总括文件,interface一般在那里,然后看不同实现
最后找场景,看哪种情况用哪种实现

type Interface interface {
    //protocol:tcp or udp;   mapping is a port on the local machine map to the router
    AddMapping(protocol string, extport, intport int, name string, lifetime time.Duration) error   --核心目的还是在公网暴露
    DeleteMapping(protocol string, extport, intport int) error
    ExternalIP() (net.IP, error)
    String() string
}

四种实现

4. 当时没有发现一些精妙之处

比如 端口映射的定时刷新,golang用了timer,刷新其实是个单向的chan,到点涌出消息,这个比java自己的实现要好太多,比C也方便很多,所以golang能够火是有理由的
go语言chan的实现原理.md


重要心得,如何快速读代码?

这2次读代码的遭遇的前后对比,我觉得读代码最重要的是“胸有成竹”,带着预见性去读代码。
比如如上四种实现中,我看到接口,就猜测ExtIP的实现一定很简单,因为已经达到了暴露公网的目的,很可能只是个dummy,后来看下去,果然:

其他两种(Upnp&PMP)实现就复杂了,注意doit函数,是一个发现对方设备的过程

func startautodisc(what string, doit func() Interface) Interface {
    // TODO: monitor network configuration and rerun doit when it changes.
    return &autodisc{what: what, doit: doit}
}

AddMapping 本身简单,就是等发现,发现后加入map,发现过程复杂,被抽象成函数,Upnp&PMP可能还有不同的版本

所以读代码有点像佛教里面的“以行证信”,你心里已经有很清晰的印象了,读的过程是对你所信的一个验证的过程。如果初读还是很模糊,我建议是暂停读,做些准备活动,把对golang的理解,对业务的理解提升上来再去读,才能达到事半功倍的效果。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/1498782.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-25
下一篇 2022-06-25

发表评论

登录后才能评论

评论列表(0条)

保存