2

如果您查看此 go-cardano-client 如何使其成为握手请求有效负载:

https://github.com/gocardano/go-cardano-client/blob/master/shelley/handshake.go#L64

  versionTable.Add(cbor.NewPositiveInteger8(1), cbor.NewPositiveInteger(764824073))
  versionTable.Add(cbor.NewPositiveInteger16(32770), cbor.NewPositiveInteger(764824073))
  versionTable.Add(cbor.NewPositiveInteger16(32771), cbor.NewPositiveInteger(764824073))

但是grpc生成的结构是:

type HandshakeRequest struct {
  // Nonce for the server to authenticate its node ID with.
  Nonce []byte `protobuf:"bytes,1,opt,name=nonce,proto3" json:"nonce,omitempty"`
}

而这个 []byte 需要通过nonce引用:

https://github.com/input-output-hk/jormungandr/blob/master/jormungandr/src/network/service.rs#L60

它的长度为 32:

https://github.com/input-output-hk/jormungandr/blob/master/jormungandr/src/network/client/connect.rs#L58

https://github.com/input-output-hk/jormungandr/blob/6f324b706a13273afb6a0808e589735020bb59da/jormungandr/src/network/mod.rs#L73

所以golang代码中的这一行:

  versionTable.Add(cbor.NewPositiveInteger8(1), cbor.NewPositiveInteger(764824073))

不能是长度 32 []byte 对吗?我该如何编码:

  req := HandshakeRequest{}
  req.Nonce = []byte{}
  for i := 0; i < 32; i++ {
    req.Nonce = append(req.Nonce, byte(rand.Intn(256)))
  }

进入这个版本表“参数”?

另见原型

4

1 回答 1

0

编辑:您似乎假设握手gocardano/go-cardano-client和以某种方式描述的握手node.proto与相同的实现有关。事实上,我不认为他们这样做。

基于 TCP 的握手遵循 Shelley 协议规范,并使用编码的versionTable. 相反,正如您所考虑的那样,基于 gRPC 的HandshakeRequest只是一个随机数。原型模式中没有任何暗示雪莱协议的内容。该Nonce领域的评论也非常明确地说:“服务器用来验证其节点 ID 的 Nonce。

所以假设这个随机数和有效载荷有任何共同点会有点奇怪versionTable

编辑2:此外,似乎“Jormungandr”锈节点实现根本不支持雪莱,所以当你说你不能连接到中继拓扑中的节点时,我认为你不应该在Jormungandr 存储库。相反,我认为中继运行Ouroboros 网络的 Haskell 实现。

现在至于为什么无法连接,go-cardano客户端会对一些未经检查的类型断言感到恐慌,因为在QueryTipShelley 消息之后chainSyncBlocks.RequestNext,中继服务器以完全不同的迷你协议进行响应,transactionSubmission.msgRequestTxIds如使用 TCP 运行客户端并跟踪消息所示:

MiniProtocol: 4 / MessageMode: 1 / f1bb7f80800400058400f50003
Array: [4]
  PositiveInteger8(0)
  False
  PositiveInteger8(0)
  PositiveInteger8(3)

2使用 MiniProtocol ( )发送同步链请求时,您也会得到相同的结果ChainSyncHeaders。我检查了 Shelley 协议规范,但找不到关于服务器为什么会切换协议的明确指示......不幸的是,我对 Haskell 不够熟悉,无法从 Ouroboros 资源中获得进一步的了解。


在 proto 中的 nonceHandshakeRequest确实与 Shelley 协议相关的意外情况下,其内容可能是您链接的 Cardano 客户端中的 CBOR 数组(推测如下):

    arr := cbor.NewArray()
    arr.Add(cbor.NewPositiveInteger8(handshakeMessagePropose))
    versionTable := cbor.NewMap()
    arr.Add(versionTable)

    versionTable.Add(...)
    versionTable.Add(...)
    versionTable.Add(...)

    return []cbor.DataItem{arr}

通过检查使用握手请求的客户端,我们可以看到:

messageResponse, err := c.queryNode(multiplex.MiniProtocolIDMuxControl, handshakeRequest())

然后在queryNode

sdu := multiplex.NewServiceDataUnit(miniProtocol, multiplex.MessageModeInitiator, dataItems)
...
c.socket.Write(sdu.Bytes())

sdu.Bytes()方法序列化整个有效负载,特别是:

// EncodeList return CBOR representation for each item in the list
func EncodeList(list []DataItem) []byte {
    result := []byte{}
    for _, item := range list {
        result = append(result, item.EncodeCBOR()...)
    }
    return result
}

EncodeCBOR()方法由函数中的 theArrayMapused 实现handshakeRequest() []cbor.DataItem。请注意,握手函数返回一个切片[]cbor.DataItem,其中包含一个Array项目,该项目包含(如文档所述)handshakeMessageProposeversionTable地图。

如果您仔细遵循序列化的过程,您最终将获得字节数组的细分——以下为十进制:

[130 0 163 1 26 45 150 74 9 25 128 2 26 45 150 74 9 25 128 3 26 45 150 74 9]

在哪里:

  • 130是数组数据项前缀
  • 0 是handshakeMessagePropose
  • 163是地图数据项前缀
  • 随后的字节是versionTable地图

它总共是 25 个字节。在这一点上,我不知道内置queryNode函数的多路复用包装器是否是随机数的一部分。使用完整的包装器,序列化字节数组的长度最多为 33。因此,不包括一些控制位或诸如此类的东西,这可能是您应该写入HandshakeRequest.Nonce.

于 2021-03-25T22:03:20.847 回答