听 GPT 讲 Go-Ethereum 源代码 (24)

分享更多精彩内容,欢迎关注!

alt

File: p2p/simulations/connect.go

在go-ethereum项目中,p2p/simulations/connect.go文件用于实现模拟网络中节点连接的功能。

ErrNodeNotFound是一个错误变量,用于表示节点未找到的错误情况。

ConnectToLastNode函数用于将一个节点连接到最后一个节点。它首先检查模拟网络中是否已经有节点存在,如果有,则获取最后一个节点的地址,并将新节点连接到该地址。

ConnectToRandomNode函数用于将一个节点连接到随机选择的另一个节点。它通过调用SelectRandomNode函数来选择一个随机节点,并将新节点连接到该随机节点的地址。

ConnectNodesFull函数用于将多个节点连接成一个完全连接的网络。它通过遍历所有节点,并将其与其他所有节点进行连接来实现完全连接。

ConnectNodesChain函数用于将多个节点连接成一个链状网络。它通过遍历所有节点,并将其连接到前一个节点的地址来实现链状连接。

connectNodesChain函数是ConnectNodesChain函数的内部函数,用于连接两个节点。

ConnectNodesRing函数用于将多个节点连接成一个环状网络。它通过遍历所有节点,并将其连接到前一个节点的地址,最后一个节点连接到第一个节点的地址来实现环状连接。

ConnectNodesStar函数用于将多个节点连接成一个星状网络。它通过将所有节点连接到一个中心节点的地址来实现星状连接。

connectNotConnected函数是一个通用的连接函数,使用给定的地址连接节点,并处理连接错误。

ignoreAlreadyConnectedErr函数是一个通用的连接函数,用于连接节点,但忽略已经连接的错误。

这些函数共同实现了节点连接的各种方式,如链状、环状、星状等,并提供了通用的连接功能。这些功能在模拟网络中起到了重要的作用,用于模拟真实网络中的节点连接行为。

File: p2p/netutil/toobig_notwindows.go

在go-ethereum项目中,p2p/netutil/toobig_notwindows.go文件的作用是实现了一些函数来判断网络消息是否过大。

该文件的核心是isPacketTooBig函数,它用于检查网络消息是否超过了操作系统的限制大小。isPacketTooBig函数调用了一系列辅助函数来判断消息的大小。

详细来说,isPacketTooBig函数首先获取操作系统对消息大小的限制值,然后根据消息的类型检查其大小是否超过该限制。根据不同的消息类型,isPacketTooBig函数调用了以下几个辅助函数:

  1. isPacketTooBigIPv4:用于检查IPv4消息的大小是否超过限制。
  2. isPacketTooBigIPv6:用于检查IPv6消息的大小是否超过限制。
  3. isPacketTooBigLocal:用于检查本地消息的大小是否超过限制。

这些辅助函数根据操作系统的不同,调用了不同的系统函数来获取消息的最大限制大小。例如,在Linux系统下,它们可能会调用syscall包中的GetsockoptInt函数来获取SO_{RCV,TX}BUF选项的大小。

通过这些辅助函数的协同工作,isPacketTooBig函数可以准确地判断出网络消息是否过大。

总结起来,p2p/netutil/toobig_notwindows.go文件的作用是在go-ethereum项目中实现了一些函数,用于判断网络消息是否过大。这些函数包括isPacketTooBig和它的辅助函数,通过检查消息的大小和操作系统的限制来确定消息是否过大。

File: p2p/netutil/toobig_windows.go

在go-ethereum项目中,p2p/netutil/toobig_windows.go文件的作用是为Windows系统提供用于处理网络连接的辅助功能。该文件中的函数主要用于判断网络数据包的大小是否超过限制,并提供了一些处理相关错误的方法。

现在来详细介绍一下isPacketTooBig这几个函数的作用:

  1. isPacketTooBig(err error) bool: 该函数用于判断给定的错误err是否表示网络数据包过大。它通过检查错误的类型和错误码来判断。如果错误类型为"syscall.Errno"且错误码为WSAECONNRESET(10054)或WSAECONNABORTED(10053),则表示网络数据包过大。

  2. handlePacketTooBig(err error, c syscall.Handle) error: 该函数用于处理网络数据包过大的错误,并返回一个适当的错误信息。它根据不同的错误类型和错误码执行不同的处理逻辑。如果错误类型为"syscall.Errno"且错误码为WSAECONNRESET(10054)或WSAECONNABORTED(10053),则表示连接被重置或中止,此时会返回一个错误信息"connection reset"。否则,将返回原始的错误信息。

  3. handleSocketError(syscall.Errno, c syscall.Handle) error: 该函数用于处理底层套接字发生错误的情况,并返回一个适当的错误信息。它针对不同的错误码执行不同的处理逻辑,如WSAECONNRESET(10054)或WSAECONNABORTED(10053)时,返回一个错误信息"connection reset"。

总之,p2p/netutil/toobig_windows.go文件提供了一些用于处理网络连接和错误的辅助函数,主要用于判断网络数据包的大小是否超过限制,并提供了相应的错误处理逻辑。

File: p2p/simulations/mocker.go

在go-ethereum项目中,p2p/simulations/mocker.go文件是用于对以太坊节点之间的网络通信进行模拟和测试的工具。

该文件中的mockerList变量是一个用于存储所有模拟节点的列表。每个节点都通过mocker类型表示,其中包含了该节点的网络信息以及与其他节点之间的连接信息。

  • LookupMocker函数用于根据节点的ID查找对应的模拟节点。
  • GetMockerList函数返回所有已创建的模拟节点列表。
  • boot函数用于启动模拟节点的网络连接,并设置节点间的相互连接关系。
  • startStop函数用于启动或停止模拟节点的网络服务。
  • probabilistic函数用于模拟节点之间的网络连接概率。
  • connectNodesInRing函数用于在模拟网络中创建一个环形拓扑结构,即把所有节点按照顺序连接成一个环。

通过使用这些函数,可以方便地创建和管理模拟节点,以模拟和测试以太坊网络的各种情况和性能。

File: p2p/metrics.go

在go-ethereum项目中,p2p/metrics.go文件的作用是实现度量和记录节点之间的网络流量、连接以及其他相关指标的功能。

下面介绍一下变量的作用:

  • activePeerGauge:用于度量当前活跃对等节点的数量。
  • ingressTrafficMeter:用于度量节点接收到的入站网络流量。
  • egressTrafficMeter:用于度量节点发送的出站网络流量。
  • serveMeter:用于度量节点收到的入站连接数量。
  • serveSuccessMeter:用于度量节点成功处理的入站连接数量。
  • dialMeter:用于度量节点发起的外拨连接数量。
  • dialSuccessMeter:用于度量节点成功建立的外拨连接数量。
  • dialConnectionError:用于记录节点外拨连接失败的次数。
  • dialTooManyPeers:用于记录节点因已达到连接上限而无法建立外拨连接的次数。
  • dialAlreadyConnected:用于记录节点试图与已连接的对等节点建立重复连接的次数。
  • dialSelf:用于记录节点试图与自己建立连接的次数。
  • dialUselessPeer:用于记录节点试图与非边缘节点建立无意义连接的次数。
  • dialUnexpectedIdentity:用于记录节点试图与提供无效身份验证信息的对等节点建立连接的次数。
  • dialEncHandshakeError:用于记录节点在与对等节点进行加密握手过程中出现错误的次数。
  • dialProtoHandshakeError:用于记录节点在与对等节点进行协议握手过程中出现错误的次数。

以下是一些结构体的作用:

  • meteredConn:一个基于net.Conn接口的结构体,用于包装一个网络连接并对其进行流量计量。
  • init:用于初始化度量统计数据结构的函数。
  • markDialError:用于记录外拨连接错误的函数。
  • newMeteredConn:用于创建一个带有流量计量的网络连接。
  • Read:重写了meteredConn的Read方法,用于实现网络流量的计量。
  • Write:重写了meteredConn的Write方法,用于实现网络流量的计量。

总的来说,p2p/metrics.go文件通过使用这些变量和函数,实现了对节点之间网络流量、连接数及其他指标的度量和统计。这些度量和统计的数据对于监控网络性能和协议的正确性非常重要。

File: p2p/netutil/net.go

在go-ethereum项目中,p2p/netutil/net.go文件是一个网络工具包,提供了一些用于处理网络相关操作的函数和结构体。

lan4,errInvalid,errUnspecified,errSpecial,errLoopback,errLAN这几个变量用于定义不同类型的网络,例如lan4表示IPv4局域网,errInvalid表示无效的网络类型,errUnspecified表示未指定网络类型,等等。

Netlist结构体表示一个网络列表,用于存储网络类型。DistinctNetSet是一个存储唯一网络类型的集合。

init函数主要用于初始化网络类型列表,将预定义的网络类型加入到Netlist中。

ParseNetlist函数用于解析字符串形式的网络列表,并返回Netlist。

MarshalTOML和UnmarshalTOML函数用于将网络列表转换为TOML格式或从TOML格式转换为Netlist。

Add函数用于将网络类型加入到Netlist中。

Contains函数用于判断一个网络列表是否包含指定的网络类型。

IsLAN函数用于判断一个网络类型是否为局域网。

IsSpecialNetwork函数用于判断一个网络类型是否为特殊网络。

CheckRelayIP函数用于检查中继IP地址是否有效。

SameNet函数和sameNet方法用于判断两个网络类型是否相同。

Remove函数用于从网络列表中移除指定的网络类型。

Len函数用于获取网络类型列表的长度。

key方法用于生成一个网络类型的唯一标识符。

String方法用于将网络类型转换为字符串表示。

File: p2p/enode/nodedb.go

p2p/enode/nodedb.go文件在go-ethereum项目中是用来处理节点数据库的功能。该文件定义了一系列结构体和函数,用于存储和管理节点信息。

  • errInvalidIP和zeroIP是常量错误值,用于表示无效的IP地址和全0的IP地址。
  • DB结构体是节点数据库的主要结构,用于存储和管理节点数据。它包括了一个底层的存储引擎(memory或者persistent),一个用于缓存的LRU cache,以及一些管理节点数据的方法。
  • OpenDB函数用于打开一个节点数据库,根据传入的参数选择使用内存存储引擎还是持久存储引擎。
  • newMemoryDB函数用于创建一个基于内存的节点数据库。
  • newPersistentDB函数用于创建一个基于持久存储引擎的节点数据库,会使用指定的文件路径和数据库类型。
  • nodeKey和splitNodeKey函数用于生成和解析节点的唯一标识键。
  • nodeItemKey和splitNodeItemKey函数用于生成和解析节点信息存储的键。
  • v5Key用于指定v5协议中的键。
  • localItemKey函数用于生成本地节点信息存储的键。
  • fetchInt64和storeInt64函数用于读取和存储int64类型的数据。
  • fetchUint64和storeUint64函数用于读取和存储uint64类型的数据。
  • Node结构体定义了一个节点的信息,包括enode URL、公钥、IP地址等。
  • mustDecodeNode函数用于解码节点信息。
  • UpdateNode函数用于更新节点信息。
  • NodeSeq结构体代表一个节点序列,用于定义节点在数据库中的位置。
  • Resolve函数用于解析节点的enode URL。
  • DeleteNode函数用于删除指定的节点。
  • deleteRange函数用于删除指定范围内的节点。
  • ensureExpirer函数用于确保定期清理过期的节点。
  • expirer函数用于定期清理过期的节点。
  • expireNodes函数用于清理过期的节点。
  • LastPingReceived和UpdateLastPingReceived函数分别用于获取和更新节点的最后一次ping请求的时间。
  • LastPongReceived和UpdateLastPongReceived函数分别用于获取和更新节点的最后一次pong响应的时间。
  • FindFails和UpdateFindFails函数分别用于获取和更新节点的失败查找次数。
  • FindFailsV5和UpdateFindFailsV5函数分别用于获取和更新节点在v5协议中的失败查找次数。
  • localSeq和storeLocalSeq函数分别用于获取和存储本地节点的序列号。
  • QuerySeeds函数用于查询种子节点。
  • nextNode函数用于获取下一个节点。
  • Close函数用于关闭节点数据库。

以上是p2p/enode/nodedb.go文件中的一些重要功能和变量的作用,它们共同实现了对节点信息的存储和管理,包括添加、更新、删除等操作。

File: p2p/peer_error.go

在go-ethereum项目中,p2p/peer_error.go文件的作用是定义了与对等节点通信过程中出现的错误相关的数据类型和函数。

errorToString变量是一个映射表,它将对等节点通信过程中可能出现的错误码映射为相应的描述字符串。这个变量的作用是方便将错误码转化为可读的描述。

errProtocolReturned变量是一个错误状态标识,用于表示在对等节点通信过程中,远程节点返回了一个错误。

discReasonToString变量是一个映射表,将与断开连接原因(DISC_REASON)相关的整数值映射为相应的描述字符串。它的作用是将数字形式的断开连接原因转化为可读的描述。

peerError结构体用于表示对等节点通信过程中的错误。它包含了一个错误码和一个错误信息字段,用于描述错误的具体内容。该结构体的作用是方便在代码中传递和处理错误。

DiscReason结构体用于表示与断开连接原因相关的数据。它包含了一个整数值和一个可选的附加信息字段。该结构体的作用是方便在代码中传递和记录断开连接的原因。

newPeerError函数用于创建一个新的peerError结构体。它接收一个错误码和一个错误描述作为参数,并返回一个对应的peerError结构体。

Error函数是peerError结构体的方法,用于返回该错误的描述信息。

String函数是DiscReason结构体的方法,用于返回与该断开连接原因相关的描述信息。

discReasonForError函数是一个错误码到断开连接原因的映射函数。它接收一个错误码参数,并返回对应的断开连接原因(DISC_REASON)。它的作用是方便将错误码转化为断开连接原因。

File: p2p/simulations/adapters/exec.go

在go-ethereum项目中,p2p/simulations/adapters/exec.go文件是用于创建一个仿真适配器,该适配器可以在一个单独的进程中执行以太坊节点。这样做的目的是为了在模拟网络环境中更好地测试和研究以太坊网络。

以下是各个结构体的作用:

  1. ExecAdapter:仿真适配器的主要结构体,它负责创建和管理执行节点。

  2. ExecNode:执行节点结构体,表示一个运行的以太坊节点。

  3. execNodeConfig:节点配置结构体,用于存储节点的各种配置选项。

  4. nodeStartupJSON:节点启动配置结构体,用于存储节点的启动配置信息。

  5. SnapshotAPI:快照API结构体,用于提供节点的快照功能。

  6. wsRPCDialer:WebSocket RPC拨号器结构体,用于与节点建立WebSocket RPC连接。

以下是各个函数的作用:

  1. init:初始化函数,用于设置日志和注册执行节点。

  2. NewExecAdapter:创建新的仿真适配器。

  3. Name:返回适配器的名称。

  4. NewNode:创建新的执行节点。

  5. Addr:返回节点的地址。

  6. Client:返回节点的客户端。

  7. Start:启动节点,并等待节点启动完成。

  8. waitForStartupJSON:等待节点启动配置。

  9. execCommand:执行命令行命令。

  10. Stop:停止节点。

  11. NodeInfo:返回节点的信息。

  12. ServeRPC:提供RPC服务。

  13. wsCopy:将数据从一个WebSocket连接复制到另一个连接。

  14. Snapshots:获取节点的快照列表。

  15. initLogging:初始化日志记录。

  16. execP2PNode:执行P2P节点。

  17. startExecNodeStack:启动执行节点堆栈。

  18. Snapshot:创建节点的快照。

  19. DialRPC:拨号到RPC服务器。

这些函数和结构体的组合提供了一个完整的仿真环境,用于模拟以太坊网络中的节点行为,并允许进行各种测试和研究。通过创建和管理执行节点,可以更好地理解和调试以太坊网络行为。

File: p2p/netutil/error.go

在go-ethereum项目中,p2p/netutil/error.go文件是网络工具包的一部分,其目的是提供网络错误的处理和判断函数。这个文件中的函数主要用于处理网络相关的错误情况,例如临时错误和超时错误。

具体函数的作用如下:

  1. IsTemporaryError(err error) bool:判断给定的错误是否是临时错误。临时错误是指在网络通信中可能出现的暂时错误,例如连接中断、连接重置或连接超载等。该函数接收一个错误作为输入,并返回一个布尔值,用于指示给定的错误是否属于临时错误。

  2. IsTimeout(err error) bool:判断给定的错误是否是超时错误。超时错误是指在网络通信中可能出现的请求超时或响应超时等错误。该函数接收一个错误作为输入,并返回一个布尔值,用于指示给定的错误是否属于超时错误。

这些函数在网络通信中非常有用,可以帮助开发人员处理和判断不同类型的网络错误。在应用程序中,可以使用这些函数来确定错误的类型,并根据需要执行相应的操作,例如重新连接、重试请求或记录错误日志。

File: p2p/simulations/simulation.go

在go-ethereum项目中,p2p/simulations/simulation.go文件是用于模拟网络行为和交互的文件。

Simulation结构体代表一个网络模拟实例,它包含了所有参与者和他们之间的连接。Step结构体定义了网络模拟中的一步操作,例如发送消息或执行某个动作。Expectation结构体表示预期的一步操作,它用于检查模拟是否按照预期执行。StepResult结构体用于记录每次模拟执行的结果。

NewSimulation函数用于创建一个新的网络模拟实例,它接收参与者和连接作为参数,并返回一个Simulation结构体。Run函数用于运行网络模拟,它接收一个或多个Step结构体作为参数,并按顺序执行这些步骤。watchNetwork函数用于监听网络事件,例如消息的发送和接收。newStepResult函数用于创建一个新的StepResult结构体,用于记录每次模拟的结果。

总体而言,这些结构体和函数提供了一种在go-ethereum项目中进行网络模拟和测试的机制,可以模拟出实际网络环境中的交互和行为。

File: p2p/discover/v5wire/session.go

在go-ethereum项目中,p2p/discover/v5wire/session.go文件的作用是实现P2P网络中的会话管理和握手过程。

以下是每个结构体和函数的详细解释:

  1. SessionCache 结构体:是会话缓存,用于存储已建立的会话。

  2. sessionID 结构体:用于唯一标识一个会话,是一个128位的随机数。

  3. session 结构体:代表一个会话对象,包含了会话的相关信息,如远程节点的地址、会话ID、密钥等。

    • HandshakeSent:表示是否已发送握手消息。
    • RemotePublicKey:远程节点的公钥。
    • EarlySecret、HandshakeSecret、TransportSecret:用于密钥交换过程的加密密钥。
    • EarlyNonce、HandshakeNonce、TransportNonce:用于密钥交换过程的加密随机数。
    • EarlyCipher、HandshakeCipher、TransportCipher:用于密钥交换过程的加密模块。
    • EarlyDecoder、HandshakeDecoder、TransportDecoder:用于解密收到的消息。
    • EarlyEncoder、HandshakeEncoder、TransportEncoder:用于加密发送的消息。
  4. keysFlipped 函数:用于判断是否在握手过程中切换密钥对。

  5. NewSessionCache 函数:创建一个新的会话缓存。

  6. generateNonce 函数:生成一个随机的加密随机数。

  7. generateMaskingIV 函数:生成一个随机的初始化向量。

  8. nextNonce 函数:生成下一个加密随机数。

  9. readKey 函数:从输入密钥派生一个新的加密密钥。

  10. storeNewSession 函数:将新的会话存储到会话缓存。

  11. getHandshake 函数:从会话缓存中获取与远程节点的握手状态。

  12. storeSentHandshake 函数:存储已发送的握手消息。

  13. deleteHandshake 函数:从握手列表中删除握手消息。

  14. handshakeGC 函数:对握手状态进行垃圾回收,清理超时的握手消息。

总之,session.go 文件中的结构体和函数提供了会话管理、密钥交换和握手过程的实现,用于保证节点之间的安全通信。

File: p2p/simulations/examples/ping-pong.go

在go-ethereum项目中,p2p/simulations/examples/ping-pong.go文件的作用是提供一个简单的示例程序,用于演示通过P2P网络发送ping-pong消息。

该文件中的adapterType变量是用于选择用于模拟网络的适配器类型的。它可以是"inmem"、"udp"或"tcp",分别表示在内存、UDP或TCP上模拟网络。

pingPongService结构体是一个简单的服务,它包含了与ping-pong相关的状态和操作。它有两个字段:pingCount和pongCount,分别用于计算收到的ping和pong消息的数量。

main函数是程序入口点,它初始化了一个新的pingPongService,并调用Start函数启动该服务。然后,它会通过调用Protocols函数向p2p模拟器注册协议,并通过调用Run函数来实际运行模拟器。

newPingPongService函数是用于创建一个新的pingPongService实例的辅助函数。它返回一个指向pingPongService的指针,并初始化pingCount和pongCount为零。

Protocols函数返回一系列协议,用于在网络上传输ping和pong消息。

Start函数是用于启动pingPongService的函数。它为服务的每个注册协议创建一个侦听器,并在后台运行一个goroutine来接受和处理传入的消息。

Stop函数是用于停止pingPongService的函数。它关闭服务的所有侦听器,并终止后台goroutine。

Info函数返回关于服务状态的一些信息,如收到的ping和pong消息的数量。

Run函数是模拟器的主循环函数。它基于时间触发ping和pong消息的发送,并处理模拟器中到达的消息。

通过运行该示例程序,可以模拟一个简单的P2P网络,其中节点之间可以相互发送ping和pong消息。

File: p2p/enode/urlv4.go

在go-ethereum项目中,p2p/enode/urlv4.go文件的作用是定义和实现Enode URL的v4版本。Enode URL是用于标识和定位Ethereum网络中的节点的一种格式。

在该文件中,包含以下一些变量和函数:

  1. incompleteNodeURL: 这是一个常量,表示不完整的Enode URL的前缀,用于生成不完整的Enode URL。
  2. lookupIPFunc: 这是一个函数类型的变量,用于查找给定主机名的IP地址。它被用于解析Enode URL中的主机名。

以下是一些主要函数的作用:

  1. MustParseV4: 这是一个辅助函数,用于解析Enode URL字符串,将其转换为URLv4类型的实例。如果解析失败,则会引发panic。
  2. ParseV4: 这是一个辅助函数,用于解析Enode URL字符串,将其转换为URLv4类型的实例。与MustParseV4不同的是,如果解析失败,它会返回一个错误。
  3. NewV4: 这是一个构造函数,用于创建一个新的URLv4实例,表示给定的节点和Enode URL。
  4. isNewV4: 这是一个辅助函数,用于检查给定的字符串是否表示一个有效的Enode URLv4。
  5. parseComplete: 这是一个辅助函数,用于解析完整的Enode URL字符串,将其转换为URLv4类型的实例。如果解析失败,它会返回一个错误。
  6. parsePubkey: 这是一个辅助函数,用于从Enode URL中解析公钥,并返回一个crypto.Pubkey类型的实例。
  7. URLv4: 这是一个结构体类型,表示Enode URL的v4版本。它包含Enode ID、IP地址、端口号和公钥等信息。
  8. PubkeyToIDV4: 这是一个辅助函数,用于从给定的公钥计算并返回Enode ID。

总的来说,p2p/enode/urlv4.go文件定义和实现了Enode URL的v4版本的解析和构造方法,以及相关的辅助函数。它提供了一种方便的方式来处理和操作Enode URL,从而定位和连接到Ethereum网络中的节点。

File: p2p/dial.go

p2p/dial.go文件是go-ethereum项目中的一部分,用于实现节点之间的拨号功能。它包含了一些常量、变量和函数,用于处理拨号相关的逻辑。

以下是对提到的一些常量的解释:

  • errSelf:表示尝试与自身节点建立连接时的错误。
  • errAlreadyDialing:表示已经在尝试与目标节点建立连接时的错误。
  • errAlreadyConnected:表示已经与目标节点建立连接时的错误。
  • errRecentlyDialed:表示最近已经与目标节点建立连接过的错误。
  • errNetRestrict:表示当前网络限制无法与目标节点建立连接的错误。
  • errNoPort:表示没有可用端口进行连接的错误。

以下是对提到的一些结构体的解释:

  • NodeDialer:负责拨号逻辑和与节点建立连接。
  • nodeResolver:负责节点地址的解析。
  • tcpDialer:负责基于TCP协议的拨号和连接。
  • dialScheduler:负责调度拨号任务。
  • dialSetupFunc:拨号前的准备工作函数。
  • dialConfig:拨号配置信息。
  • dialTask:拨号任务。
  • dialError:拨号错误信息。

以下是对提到的一些函数的解释:

  • Dial:封装了节点的拨号和连接逻辑。
  • nodeAddr:从提供的主机地址和端口构建节点地址。
  • withDefaults:使用默认配置填充给定的拨号配置信息。
  • newDialScheduler:创建一个新的拨号调度器。
  • stop:停止拨号调度器。
  • addStatic:向静态拨号池中添加节点。
  • removeStatic:从静态拨号池中移除节点。
  • peerAdded:当新节点被添加时的处理逻辑。
  • peerRemoved:当节点移除时的处理逻辑。
  • loop:拨号循环,用于按照调度规则执行拨号任务。
  • readNodes:从文件中读取节点列表。
  • logStats:记录拨号和连接的统计信息。
  • rearmHistoryTimer:重置历史记录计时器。
  • expireHistory:清除过时的历史记录。
  • freeDialSlots:释放已完成的拨号任务占用的拨号槽位。
  • checkDial:检查拨号任务是否可以开始。
  • startStaticDials:初始化静态拨号任务。
  • updateStaticPool:更新静态拨号池中的节点列表。
  • addToStaticPool:向静态拨号池中添加节点。
  • removeFromStaticPool:从静态拨号池中移除节点。
  • startDial:开始一个新的拨号任务。
  • newDialTask:创建一个新的拨号任务。
  • run:执行拨号任务。
  • needResolve:检查是否需要解析主机地址。
  • resolve:解析主机地址。
  • dial:执行拨号操作。
  • String:将节点地址转换为字符串表示。
  • cleanupDialErr:清理拨号错误消息。

File: p2p/dnsdisc/doc.go

在go-ethereum项目中,p2p/dnsdisc/doc.go是一个文档文件,用于说明p2p/dnsdisc包的功能和使用方法。

该文件起到了多个方面的作用。首先,它提供了对p2p/dnsdisc包的总体介绍,包括该包所实现的功能、其目的以及其与其他相关模块的关系。这使得开发者可以了解到该包适用于哪些场景,以及它在整个go-ethereum项目中所处的位置。

其次,该文件还提供了关于p2p/dnsdisc包的详细说明。它描述了该包中所有的类型、函数、接口和常量,并说明了它们的作用和使用方法。这使得开发者在使用该包时可以轻松地查找相关的信息,并理解各个组件之间的交互方式。

除了对包本身的描述外,p2p/dnsdisc/doc.go文件还包含了一些示例代码,展示了如何使用该包来实现特定的功能。这些示例代码可以帮助开发者更好地理解如何使用该包以及如何在现有的代码中整合它的功能。

最后,该文件还提供了一些关于该包的一般的使用建议和注意事项。它指导开发者如何正确使用该包,以及如何处理可能出现的错误或异常情况。

总之,p2p/dnsdisc/doc.go文件在go-ethereum项目中起到了对p2p/dnsdisc包进行详细介绍和说明的作用。它使开发者能够了解该包的功能、使用方法和最佳实践,从而更加高效地使用和开发该项目。

File: p2p/discover/v5wire/encoding.go

文件p2p/discover/v5wire/encoding.go的作用是实现了v5wire包中的消息编码和解码功能,用于在以太坊go-ethereum项目的p2p网络中,进行v5版本的节点间通信。

以下是所列变量和结构体的作用:

  • DefaultProtocolID:默认的协议ID。
  • errTooShort:长度过短错误。
  • errInvalidHeader:无效的头错误。
  • errInvalidFlag:无效的标志错误。
  • errMinVersion:最小版本错误。
  • errMsgTooShort:消息长度过短错误。
  • errAuthSize:认证数据大小错误。
  • errUnexpectedHandshake:意外的握手错误。
  • errInvalidAuthKey:无效的认证密钥错误。
  • errNoRecord:没有记录错误。
  • errInvalidNonceSig:无效的Nonce签名错误。
  • errMessageTooShort:消息长度过短错误。
  • ErrInvalidReqID:无效的请求ID错误。
  • sizeofStaticHeader:静态头大小。
  • sizeofWhoareyouAuthData:whoareyou认证数据的大小。
  • sizeofHandshakeAuthData:握手认证数据的大小。
  • sizeofMessageAuthData:消息认证数据的大小。
  • sizeofStaticPacketData:静态数据包的大小。

以下是所列函数的作用:

  • IsInvalidHeader:检查头是否无效。
  • NewCodec:创建一个新的编解码器。
  • Encode:编码并加密消息。
  • EncodeRaw:编码消息。
  • writeHeaders:写入头信息。
  • makeHeader:生成头信息。
  • encodeRandom:编码随机数。
  • encodeWhoareyou:编码whoareyou消息。
  • encodeHandshakeHeader:编码握手头信息。
  • makeHandshakeAuth:生成握手认证数据。
  • encodeMessageHeader:编码消息头信息。
  • encryptMessage:加密消息。
  • Decode:解码并解密消息。
  • decodeWhoareyou:解码whoareyou消息。
  • decodeHandshakeMessage:解码握手消息。
  • decodeHandshake:解码握手。
  • decodeHandshakeAuthData:解码握手中的认证数据。
  • decodeHandshakeRecord:解码握手记录。
  • decodeMessage:解码消息。
  • decryptMessage:解密消息。
  • checkValid:检查消息是否有效。
  • mask:对字节进行掩码操作。
  • bytesCopy:复制字节。

File: p2p/simulations/adapters/inproc.go

p2p/simulations/adapters/inproc.go文件在go-ethereum项目中的作用是实现了模拟p2p网络的适配器。该适配器允许在一个进程中模拟多个P2P节点之间的通信,用于进行不同节点之间的模拟测试。

SimAdapter结构体表示一个模拟适配器对象,它包含了跟踪已创建的SimNode的映射和网络通信的相关方法。SimNode结构体表示一个模拟节点对象,它包含节点的状态和连接信息。

  • NewSimAdapter:创建一个新的SimAdapter对象。
  • Name:返回适配器的名称。
  • NewNode:创建一个新的模拟节点。
  • Dial:在两个节点之间建立点对点的直接连接。
  • DialRPC:在两个节点之间建立点对点的RPC连接。
  • GetNode:根据节点的标识返回节点对象。
  • Close:关闭适配器并停止所有节点。
  • Addr:返回适配器的地址。
  • Node:返回当前节点。
  • Client:返回适配器节点的客户端。
  • ServeRPC:启动RPC服务并处理传入的RPC请求。
  • Snapshots:返回适配器节点的快照。
  • Start:启动适配器节点。
  • Stop:停止适配器节点。
  • Service:根据给定服务类型返回给定节点的服务对象。
  • Services:返回给定节点的所有服务。
  • ServiceMap:返回适配器节点的服务映射。
  • Server:返回节点的服务器对象。
  • SubscribeEvents:订阅节点事件。
  • NodeInfo:返回节点的信息。

这些方法和结构体共同实现了模拟p2p网络场景,模拟节点之间的连接、通信和事件处理等功能。通过使用这些方法和结构体,可以方便地模拟和测试复杂的p2p网络行为。

File: p2p/protocol.go

在go-ethereum项目中,p2p/protocol.go文件定义了与Peer-to-Peer (P2P)协议相关的结构体和函数。

该文件的主要作用是定义P2P协议所需的数据结构和函数,以便在Geth节点之间进行通信和交换数据。

Protocol结构体定义了P2P协议的基本信息,包括协议名称、版本、支持的命令和消息ID等。每个支持的协议都应该定义一个对应的Protocol结构体。

Cap结构体表示节点对某个协议的能力,包括协议名称和版本。节点在发现并连接其他节点时,可以根据Cap结构体中的信息判断是否支持某个协议。

cap函数用于比较两个Cap结构体的协议能力,判断两个节点是否具有相同的协议能力。

String函数用于将Protocol结构体转换为字符串形式,方便打印和输出。

Less函数用于比较两个Protocol结构体的版本号和名称大小,用于排序和查找操作。

总的来说,p2p/protocol.go文件定义了P2P协议所需的数据结构和函数,提供了对协议的支持和封装,方便其他模块进行节点间的通信和数据交换。

File: p2p/rlpx/buffer.go

在go-ethereum项目中,p2p/rlpx/buffer.go文件的作用是为了提供一个用于读写字节的缓冲区。

readBuffer是一个结构体,用于读取数据。它有以下成员:

  • data:用于存储字节数据的切片
  • head:表示读取的起始位置
  • seq:表示读取的连续读取位置

writeBuffer是一个结构体,用于写入数据。它有以下成员:

  • Data:用于存储字节数据的缓存切片
  • Size:表示当前缓存切片的长度
  • Offset:表示字节数据的起始位置

reset函数用于重置readBuffer的状态,将head和seq都设置为0。

read函数用于从readBuffer中读取指定长度的字节数据,并将数据存储到输入的切片中。

grow函数用于增加readBuffer的大小,以便能够容纳更多的字节数据。

appendZero函数用于在readBuffer的data切片末尾追加指定数量的零字节。

Write函数用于将指定的字节数据写入writeBuffer中。如果写入的数据超过了writeBuffer的容量,它会自动调整容量。

readUint24函数用于从readBuffer中读取3字节的无符号整数。

putUint24函数用于将指定的3字节无符号整数写入writeBuffer中。

growslice函数用于按需扩展切片的长度,以便能够容纳更多的字节数据。它会返回一个新的切片,并且保留了之前的元素。

这些函数和结构体的作用是为了提供一个高效的字节数据处理工具,使得在p2p网络中进行数据传输更加方便和可靠。

File: p2p/discover/ntp.go

在Go-Ethereum项目中,p2p/discover/ntp.go文件的作用是实现与网络时间协议(Network Time Protocol,简称NTP)服务器进行交互,以检测和校准本地和远程计算机之间的时钟偏差。

在分布式系统中,各个节点的时钟必须保持同步,以确保消息和交易的时间戳正确,并且协议能够正常运行。NTP是一种网络协议,用于同步计算机的时钟,并校正时钟的漂移。

在ntp.go文件中,有几个重要的函数:

  1. checkClockDrift:该函数用于检测本地计算机的时钟漂移,并返回时钟实际与理论值之间的差异。它通过与NTP服务器进行时间同步来获取真实的时间,并与本地计算机的时钟进行比较,从而计算出时钟漂移。这个函数通过使用系统调用访问操作系统的时间设施,并结合NTP协议来获取更精确的时间。

  2. sntpDrift:该函数是NTP协议客户端的核心实现,用于与NTP服务器进行通信,获取服务器的时间戳并计算时钟偏移。它通过使用UDP协议与NTP服务器建立连接,并发送时间请求,等待服务器返回时间响应。然后,通过比较响应中的时间戳和本地计算机的时钟来计算时钟偏移。

这些功能的作用是确保节点的时钟与网络环境中的其他节点时钟保持同步。这对于一个分布式系统(如区块链)非常重要,因为它确保了时间戳的准确性,从而保证了消息和交易顺序的正确性,并且很多协议和算法都依赖于时钟同步。通过与NTP服务器进行交互,这些函数使节点能够校准本地时钟并检测时钟的漂移,从而维持和网络中其他节点的一致性。

File: p2p/rlpx/rlpx.go

p2p/rlpx/rlpx.go文件是go-ethereum项目中实现Rlpx协议的代码文件。Rlpx协议是以太坊网络中节点之间进行通信的加密和认证协议。

  • zeroHeader: 用于表示一个零值的加密帧头部。
  • errPlainMessageTooLarge: 当明文消息的长度超过最大值时返回的错误。

以下是变量的作用说明:

  • Conn: 封装了TCP连接的相关信息和方法,用于节点间建立通信。
  • sessionState: 封装了Rlpx连接的状态信息和方法,包括协商密钥、加密解密数据等。
  • hashMAC: 用于计算消息的消息验证码。
  • Secrets: 存储Rlpx连接的加密/解密密钥信息。
  • handshakeState: 用于记录Rlpx握手的状态信息。
  • authMsgV4: 表示Rlpx握手中发送的Auth消息(版本4)。
  • authRespV4: 表示Rlpx握手中发送的AuthResp消息(版本4)。

以下是结构体的作用说明:

  • newHashMAC: 创建一个hashMAC对象。
  • NewConn: 创建一个新的Rlpx连接。
  • SetSnappy: 设置是否启用Snappy压缩。
  • SetReadDeadline: 设置读取数据超时时间。
  • SetWriteDeadline: 设置写入数据超时时间。
  • SetDeadline: 设置读写数据的总超时时间。
  • Read: 从连接中读取数据。
  • readFrame: 读取一帧数据。
  • Write: 向连接中写入数据。
  • writeFrame: 写入一帧数据。
  • computeHeader: 计算帧头部的加密信息。
  • computeFrame: 计算帧数据的加密信息。
  • compute: 计算消息的合法性。
  • Handshake: 执行Rlpx握手过程。
  • InitWithSecrets: 使用给定的密钥初始化连接。
  • Close: 关闭连接。

以下是函数的作用说明:

  • runRecipient: 运行Rlpx协议的接收方逻辑。
  • handleAuthMsg: 处理Auth消息。
  • secrets: 从随机数、密钥加密数据和握手哈希计算共享密钥。
  • staticSharedSecret: 使用静态共享密钥计算动态共享密钥。
  • runInitiator: 运行Rlpx协议的发起方逻辑。
  • makeAuthMsg: 生成Auth消息。
  • handleAuthResp: 处理AuthResp消息。
  • makeAuthResp: 生成AuthResp消息。
  • readMsg: 从连接中读取消息。
  • sealEIP8: 封装EIP8帧。
  • importPublicKey: 导入公钥。
  • exportPubkey: 导出公钥。
  • xor: 实现异或操作。

File: p2p/transport.go

transport.go是go-ethereum中的一个文件,其作用是实现了RLPX(Recursive Length Prefix)协议的底层传输功能。RLPX协议是以太坊节点之间进行通信的一种协议,它建立在TCP/IP之上,用于加密和传输以太坊网络中的消息。

在transport.go文件中,最重要的结构体是rlpxTransport。它定义了一个RLPX传输实例,并且包括了传输所需要的各种参数和方法。

  1. newRLPX:此方法用于创建一个新的RLPX传输实例。它接受一些参数,如localPrivateKey(本地节点的私钥)、remotePublicKey(远程节点的公钥)等。在创建实例时,它会进行一些初始化工作,如生成临时密钥、生成握手信息等。

  2. ReadMsg:此方法用于从传输中读取消息。它会处理加密和解密的操作,通过按照RLPX协议规定的格式读取消息。

  3. WriteMsg:此方法用于向传输中写入消息。它会对消息进行加密,并按照RLPX协议规定的格式写入传输流中。

  4. close:此方法用于关闭传输。

  5. doEncHandshake:此方法用于执行加密握手。它将发送和接收节点的公钥和握手信息交换,并验证握手信息的正确性。

  6. doProtoHandshake:此方法用于执行协议握手。它将发送和接收节点的协议版本信息,并验证双方是否支持相同的协议。

  7. readProtocolHandshake:此方法用于读取协议握手消息。它会处理消息的加密和解密操作,并返回握手消息的相关信息。

通过这些方法,rlpxTransport结构体提供了对于传输的读取、写入、加密、解密、握手等功能的支持,使得节点可以使用RLPX协议进行安全的通信。

除了rlpxTransport,transport.go文件中还定义了其他一些辅助函数和常量,用于支持RLPX协议的实现和运行。

File: p2p/discover/lookup.go

在go-ethereum项目中,p2p/discover/lookup.go文件的作用是实现节点发现(node discovery)功能。节点发现是在以太坊网络中,为了在网络中查找其他节点而进行的过程。

下面是对lookup.go中的一些关键结构体和函数的详细介绍:

  1. lookup结构体:表示一个节点发现操作。它包含一个地址列表和一些用于协调和管理查找过程的变量。
  2. queryFunc函数类型:表示一个节点发现的查询操作。它接受一个地址作为参数,并返回该地址的节点信息。
  3. lookupIterator结构体:表示节点发现的迭代器。它包含一个lookup和一个索引,用于迭代地址列表。
  4. lookupFunc函数类型:表示一个节点发现的查找操作。它接受一个lookupIterator作为参数,并返回下一个地址的节点信息。
  5. newLookup函数:创建并初始化一个新的lookup结构体,并返回该结构体的指针。
  6. run函数:运行一个节点发现操作。它启动查询操作,并等待所有的查询完成。
  7. advance函数:向前移动lookup的迭代器。它更新索引并尝试获取下一个节点的地址。
  8. shutdown函数:关闭一个节点发现操作。它停止查询操作并清除所有的资源。
  9. startQueries函数:启动查询操作。它根据一定的策略获取一批地址,并为每个地址创建一个查询任务。
  10. slowdown函数:减慢查询速度。它会调整查询任务之间的发送时间间隔,以阻止发现过程在短时间内消耗大量资源。
  11. query函数:执行一个具体的查询操作。它调用queryFunc函数获取指定地址的节点信息,并将其添加到lookup的地址列表中。
  12. newLookupIterator函数:创建并初始化一个新的lookupIterator结构体。它接受一个lookup作为参数,并返回该结构体的指针。
  13. Node函数:返回当前lookupIterator指向的地址的节点信息。
  14. Next函数:移动lookupIterator到下一个地址,并返回是否成功移动。
  15. Close函数:关闭一个lookupIterator。它释放相关资源。

总之,lookup.go文件定义了节点发现的核心功能,包括创建和管理节点发现操作、执行查询操作以及迭代结果等。它为去中心化的以太坊网络提供了寻找其他节点的重要机制。

File: p2p/enode/iter.go

在go-ethereum项目中,p2p/enode/iter.go是用于处理p2p节点迭代器的文件。该文件包含多个结构体和函数,每个结构体和函数具有不同的作用。

  1. Iterator结构体:用于表示节点迭代器对象。该结构体包含一个方法Next,用于获取下一个节点。

  2. sliceIter结构体:是Iterator的具体实现,用于在切片中迭代节点。

  3. filterIter结构体:是Iterator的具体实现,用于在一个迭代器中根据筛选条件过滤节点。

  4. FairMix结构体:用于表示公平混合器对象,用于按照一定规则混合节点。

  5. mixSource结构体:用于表示混合器的源节点对象,其中包含节点切片和当前索引。

这些结构体的作用是协助实现节点迭代器的功能,包括迭代节点、筛选节点和混合节点等。

以下是一些重要的函数及其作用:

  • ReadNodes:从文件中读取节点列表,并返回一个节点迭代器。

  • IterNodes:根据给定的节点列表创建一个节点迭代器。

  • CycleNodes:根据给定的节点列表创建一个循环节点迭代器。

  • Next:获取迭代器中的下一个节点,并更新迭代器的状态。

  • Node:返回当前节点迭代器的当前节点。

  • Close:关闭迭代器。

  • Filter:根据给定的筛选条件,创建一个过滤器节点迭代器。

  • NewFairMix:创建一个公平混合器对象。

  • AddSource:向混合器添加一个源节点。

  • nextFromAny:从多个迭代器中获取下一个节点。

  • pickSource:选择一个混合器的源节点。

  • deleteSource:从混合器中删除指定的源节点。

  • runSource:按照一定的规则从混合器中获取节点,并返回下一个可用的节点。

这些函数用于实现节点迭代器的不同功能,包括读取节点、迭代节点、选择节点、混合节点和筛选节点等操作。

File: p2p/server.go

p2p/server.go文件是go-ethereum项目中实现了P2P(peer-to-peer)网络通信协议的服务器部分。它负责管理节点之间的连接、握手、消息传递等功能。

以下是对每个变量和结构体的详细说明:

  • errServerStopped:表示服务器已停止的错误。
  • errEncHandshakeError:表示加密握手过程中出错的错误。
  • errProtoHandshakeError:表示协议握手过程中出错的错误。

下面是一些重要的结构体和变量的说明:

  • Config:定义了服务器的配置参数,包括节点密钥、p2p协议版本、P2P网络ID等。
  • Server:代表P2P服务器实例,封装了网络传输层、节点信息管理等功能。
  • peerOpFunc:是一个函数类型,用于定义执行特定操作的处理函数。
  • peerDrop:定义了当连接被断开时要执行的函数。
  • connFlag:表示当前连接的状态,用于表示连接是否已停止。
  • conn:表示一个P2P连接。
  • transport:封装了底层的网络传输协议,如TCP或UDP。
  • sharedUDPConn:表示共享的UDP连接。
  • NodeInfo:表示节点的基本信息,如公钥、IP地址、端口等。

以下是一些重要的函数的说明:

  • String:将NodeInfo结构体转换为字符串表示。
  • is:检查节点是否具有特定的标志。
  • set:设置节点的标志。
  • LocalNode:返回当前节点的信息。
  • Peers:返回当前节点的所有对等节点。
  • PeerCount:返回当前节点连接的对等节点数。
  • AddPeer:向当前节点添加对等节点。
  • RemovePeer:从当前节点中移除特定的对等节点。
  • AddTrustedPeer:向当前节点添加受信任的对等节点。
  • RemoveTrustedPeer:从当前节点中移除受信任的对等节点。
  • SubscribeEvents:订阅节点事件,如新对等节点连接、断开连接等。
  • Self:返回当前节点的NodeInfo。
  • Stop:停止P2P服务器并关闭相关的网络连接。
  • ReadFromUDP:从UDP连接中读取数据。
  • Close:关闭连接。
  • Start:启动P2P服务器并开始监听连接。
  • setupLocalNode:设置当前节点的基本信息。
  • setupDiscovery:设置P2P服务器的发现服务。
  • setupDialScheduler:设置拨号计划任务。
  • maxInboundConns:设置入站连接的最大数量。
  • maxDialedConns:设置已发起连接的最大数量。
  • setupListening:设置P2P服务器的监听地址和端口。
  • setupUDPListening:设置UDP监听地址和端口。
  • doPeerOp:执行特定的对等节点操作。
  • run:启动P2P服务器并接收连接。
  • postHandshakeChecks:在握手完成后执行一些检查。
  • addPeerChecks:在添加对等节点之前执行一些检查。
  • listenLoop:监听并接受新的连接。
  • setupConn:设置一个新的连接。
  • nodeFromConn:根据连接创建一个新的节点实例。
  • checkpoint:检查连接是否是可接受的节点。
  • launchPeer:为新的连接创建一个对等节点。
  • runPeer:启动对等节点。
  • NodeInfo:返回节点的基本信息。
  • PeersInfo:返回对等节点的基本信息。

这些函数和结构体一起实现了P2P服务器的各种功能,包括节点连接管理、握手验证、消息传递等。

File: p2p/discover/table.go

在go-ethereum的p2p/discover包中,table.go的作用是实现节点发现的网络表。它负责维护已发现的节点列表,并提供节点查找、更新和删除的功能。

以下是p2p/discover/table.go文件中关键结构体的作用:

  1. Table:该结构体表示网络表,用于存储已发现的节点。它由一组bucket组成,每个bucket存储具有相同距离范围的节点。

  2. Transport:该结构体定义了网络传输的接口。它负责发送和接收节点发现消息。

  3. Bucket:该结构体用于存储一组节点。每个bucket根据节点的距离排序,并有一个最大容量限制。

  4. nodesByDistance:该结构体用于按节点ID的距离进行排序的辅助结构。

以下是p2p/discover/table.go文件中的关键函数的作用:

  1. newTable:创建一个新的Table实例。

  2. newMeteredTable:创建一个带有流量计的新Table实例。

  3. Nodes:获取表中的所有节点。

  4. self:获取本地节点的节点ID。

  5. seedRand:随机数生成器,用于从种子节点中选择用于初始发现的节点。

  6. getNode:根据节点ID选择并返回一个节点。

  7. close:关闭Table,停止刷新和验证。

  8. setFallbackNodes:设置备用种子节点。

  9. isInitDone:检查Table是否初始化完成。

  10. refresh:重新发现网络中的其他节点。

  11. loop:定期刷新节点表。

  12. doRefresh:进行实际的刷新操作。

  13. loadSeedNodes:加载种子节点。

  14. doRevalidate:执行节点验证。

  15. nodeToRevalidate:选择需要验证的下一个节点。

  16. nextRevalidateTime:获取下一次需要进行验证的时间。

  17. nextRefreshTime:获取下一次需要进行刷新的时间。

  18. copyLiveNodes:复制可用节点。

  19. findnodeByID:通过节点ID查找节点。

  20. len:获取表中节点的数量。

  21. bucketLen:获取指定bucket的节点数量。

  22. bucket:获取指定索引的bucket。

  23. bucketAtDistance:根据距离获取bucket。

  24. addSeenNode:将已看到的节点添加到表中。

  25. addVerifiedNode:将已验证的节点添加到表中。

  26. delete:从表中删除一个节点。

  27. addIP:将IP地址添加到节点。

  28. removeIP:从节点中删除IP地址。

  29. addReplacement:添加一个替代节点。

  30. replace:替换表中的一个节点。

  31. bumpInBucket:将一个节点在其bucket中上移。

  32. deleteInBucket:从bucket中删除一个节点。

  33. contains:检查表中是否包含指定的节点。

  34. pushNode:将节点添加到表中。

  35. deleteNode:从表中删除一个节点。

  36. push:向网络中的节点发送Pong消息。

本文由 mdnice 多平台发布

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值