我如何编码来自 golang 的长度为 32 [] 字节的随机数以命中 Rust 的 jormungandr rpc 服务器?
How I encode the length 32 []byte nonce from golang to hit rust's jormungandr rpc server?
如果你看看这个 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:
所以 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)))
}
进入这个版本表“params”?
编辑: 您似乎假设 gocardano/go-cardano-client
中的握手和 node.proto
中描述的握手不知何故与同一实现相关。事实上,我不认为他们这样做。
基于 TCP 的握手遵循 Shelley 协议规范并发送带有编码 versionTable
的有效载荷。正如您也考虑的那样,基于 gRPC 的 HandshakeRequest
只是一个随机数。原型模式中没有任何内容暗示 Shelley 协议。 Nonce
字段上的注释也非常明确地说:“服务器用来验证其节点 ID 的 Nonce。”
因此,假设此随机数和 versionTable
有效负载有任何共同之处,这会有点奇怪。
编辑 2:此外,“Jormungandr”rust 节点实现似乎根本不支持 Shelley,所以当你说你无法连接到节点时relay topology, I think you shouldn't look for answers in the Jormungandr repository. Instead, I think the relays run the Haskell implementations of the Ouroboros network.
现在至于为什么你不能连接,go-cardano
客户端对一些未经检查的类型断言感到恐慌,因为在 QueryTip
Shelley 消息 chainSyncBlocks.RequestNext
之后,中继服务器响应完全不同的迷你协议,transactionSubmission.msgRequestTxIds
如 运行 所示,客户端使用 TCP 并跟踪消息:
MiniProtocol: 4 / MessageMode: 1 / f1bb7f80800400058400f50003
Array: [4]
PositiveInteger8(0)
False
PositiveInteger8(0)
PositiveInteger8(3)
使用 MiniProtocol 2
(ChainSyncHeaders
) 发送同步链请求时,您也会得到相同的结果。我检查了 Shelley 协议规范,但找不到关于为什么服务器会切换协议的明确指示...不幸的是,我对 Haskell 不够熟悉,无法从 Ouroboros 来源获得进一步的见解。
在意外情况下,proto HandshakeRequest
中的随机数确实与雪莱协议相关,其内容可能是您链接的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()
方法由Array
和handshakeRequest() []cbor.DataItem
函数中使用的Map
共同实现。注意握手函数 returns 一个切片 []cbor.DataItem
,它包含一个 Array
项,其中包含(如记录的)handshakeMessagePropose
和 versionTable
映射。
如果你仔细观察序列化的过程,你最终会得到字节数组的分解——以下是十进制:
[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
.
的内容
如果你看看这个 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:
所以 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)))
}
进入这个版本表“params”?
编辑: 您似乎假设 gocardano/go-cardano-client
中的握手和 node.proto
中描述的握手不知何故与同一实现相关。事实上,我不认为他们这样做。
基于 TCP 的握手遵循 Shelley 协议规范并发送带有编码 versionTable
的有效载荷。正如您也考虑的那样,基于 gRPC 的 HandshakeRequest
只是一个随机数。原型模式中没有任何内容暗示 Shelley 协议。 Nonce
字段上的注释也非常明确地说:“服务器用来验证其节点 ID 的 Nonce。”
因此,假设此随机数和 versionTable
有效负载有任何共同之处,这会有点奇怪。
编辑 2:此外,“Jormungandr”rust 节点实现似乎根本不支持 Shelley,所以当你说你无法连接到节点时relay topology, I think you shouldn't look for answers in the Jormungandr repository. Instead, I think the relays run the Haskell implementations of the Ouroboros network.
现在至于为什么你不能连接,go-cardano
客户端对一些未经检查的类型断言感到恐慌,因为在 QueryTip
Shelley 消息 chainSyncBlocks.RequestNext
之后,中继服务器响应完全不同的迷你协议,transactionSubmission.msgRequestTxIds
如 运行 所示,客户端使用 TCP 并跟踪消息:
MiniProtocol: 4 / MessageMode: 1 / f1bb7f80800400058400f50003
Array: [4]
PositiveInteger8(0)
False
PositiveInteger8(0)
PositiveInteger8(3)
使用 MiniProtocol 2
(ChainSyncHeaders
) 发送同步链请求时,您也会得到相同的结果。我检查了 Shelley 协议规范,但找不到关于为什么服务器会切换协议的明确指示...不幸的是,我对 Haskell 不够熟悉,无法从 Ouroboros 来源获得进一步的见解。
在意外情况下,proto HandshakeRequest
中的随机数确实与雪莱协议相关,其内容可能是您链接的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()
方法由Array
和handshakeRequest() []cbor.DataItem
函数中使用的Map
共同实现。注意握手函数 returns 一个切片 []cbor.DataItem
,它包含一个 Array
项,其中包含(如记录的)handshakeMessagePropose
和 versionTable
映射。
如果你仔细观察序列化的过程,你最终会得到字节数组的分解——以下是十进制:
[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
.