美文网首页
以太坊源码分析(四 节点发现)

以太坊源码分析(四 节点发现)

作者: edolovee | 来源:发表于2018-03-23 11:04 被阅读0次

    ethereum - build unstoppable applications

    节点发现

    以太坊的节点发现协议使用的是KAD算法(kademlia)

    1. 数据存储结构
      它在一个数组里维护了256个bucket,每个bucket的数据下标即为其深度,每个bucket最多存储16个节点,所以一个节点可存储的节点数为256 * 16个节点
      这是在NodeTable中定义的


      image.png
    1. 距离算法
      每个节点都有一个nodeId,这个nodeId是根据节点的地址经过哈希算法并使用ECC加密之后,导出的一个512位的公钥
    final ECKey generatedNodeKey = ECKey.fromPrivate(sha3(addressOrEnode.getBytes()));
    
    
    public byte[] getNodeId() {
            if (nodeId == null) {
                nodeId  = pubBytesWithoutFormat(this.pub);
            }
            return nodeId;
        }
    

    两个节点的距离就是两个nodeId异或之后取最高位1所在的位置得来的,举例说明:
    假如节点A的nodeId为1011011(二进制表示),节点B的nodeId为1100110,那么二者的距离为6,距离越小那么存储的bucket越浅,也就是越近,本节点就会选取最近的16个节点发起节点查询请求

    1. 消息类型
    • ping 询问节点是否存活
    • pong ping的响应
    • findnode 节点查询,向目标节点询问附近节点列表
    • neighbours findnode消息的响应

    节点发现实现

    首先节点发现协议使用的Udp,入口是UDPListener,在这个类初始化的时候,它会读取配置文件配置(peer.discovery.ip.list)的初始化的节点发现的IP列表,然后通过start方法启动了3个任务:

    1. 节点服务端监听任务
      使用netty绑定默认为30303的端口,消息的处理器是messageHandler,收到消息的时候会使用NodeManager的handleInbound方法处理各种上面提到的消息类型
    while (!shutdown) {
        Bootstrap b = new Bootstrap();
        b.group(group)
                .channel(NioDatagramChannel.class)
                .handler(new ChannelInitializer<NioDatagramChannel>() {
                    @Override
                    public void initChannel(NioDatagramChannel ch)
                            throws Exception {
                        ch.pipeline().addLast(stats.udp);
                        ch.pipeline().addLast(new PacketDecoder());
                        MessageHandler messageHandler = new MessageHandler(ch, nodeManager);
                        nodeManager.setMessageSender(messageHandler);
                        ch.pipeline().addLast(messageHandler);
                    }
                });
    
        channel = b.bind(address, port).sync().channel();
    
        channel.closeFuture().sync();
       ...省略
    }
    
    1. 节点发现任务 每30秒向临近节点发送findnode消息
     discoverer.scheduleWithFixedDelay(
                    new DiscoverTask(nodeManager),
                    1, KademliaOptions.DISCOVER_CYCLE, TimeUnit.SECONDS);
    
    1. 刷新任务 每7200毫秒刷新下临近节点列表,其实也是发送findnode消息
    refresher.scheduleWithFixedDelay(
                    new RefreshTask(nodeManager),
                    1, KademliaOptions.BUCKET_REFRESH, TimeUnit.MILLISECONDS);
    

    相关文章

      网友评论

          本文标题:以太坊源码分析(四 节点发现)

          本文链接:https://www.haomeiwen.com/subject/ywijqftx.html