Skip to content

以太坊的NodeID

在启动Geth客户端时,会看到有如下输出内容:

image-20221207161502833

节点的NodeID在上图中已经圈出来了,这个NodeID在别人通过admin.addPeer添加节点时要作为参数传入。

这个NodeID是怎么计算出来的?

NodeID的计算

上图NodeID值如下:

enode://af18b22fcb7de98ab4ef5e0d273d516e7d31d7ebca2362a2fcf9eff821da0b6a98bea6c091743f339a8010812d94e685dc370a97a57e5134dbefd753ccf8c5d8@127.0.0.1:30303

由"enode://",一个16进制字符串,"@",IP地址和P2P端口(也是geth的TCP端口)组成。

16进制字符串

通过查看go-ethereum-1.10.26源代码,发现这个十六进制字符串是节点的ECDSA公钥的16进制形式。

也就是这里:

image-20221207162517059

再深入看下FromECDSAPub做了什么:

image-20221207162612156

S256()是ECDSA的一个曲线,包含了曲线的具体参数,再将公钥的X和Y值(一个公钥仅包含曲线参数、X、Y三个值)传入编码函数Marshal。

image-20221207162857270

可以看到,Marshal将X、Y编码为了Bytes并返回。

一直返回,最后将Bytes转为了16进制并输出。

所以,这个NodeID就是节点的公钥

我们没有创建账户,为什么会有公私钥?

在geth代码注释中,其对Node的解读为:

Node represents a host on the network.

所以在以太坊节点启动时,geth会自动随机生成一个公私钥作为节点的P2P网络身份,用于后续的P2P连接认证等用处。

可以尝试运行调试go-ethereum-1.10.26/cmd/bootnode/main.go并带上参数-genkey randomString --writeaddress查看效果。