152 lines
4.2 KiB
Nim
152 lines
4.2 KiB
Nim
# codex-dht - Codex DHT
|
|
# Copyright (c) 2022 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
#
|
|
## Discovery v5 Protocol Messages as specified at
|
|
## https://github.com/ethereum/devp2p/blob/master/discv5/discv5-wire.md#protocol-messages
|
|
## These messages get protobuf encoded, while in the spec they get RLP encoded.
|
|
##
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
import
|
|
std/[hashes, net],
|
|
bearssl/rand,
|
|
./spr,
|
|
./node,
|
|
../../../../dht/providers_messages,
|
|
../../../../dht/value_messages
|
|
|
|
export providers_messages
|
|
export value_messages
|
|
|
|
type
|
|
MessageKind* {.pure.} = enum
|
|
# TODO This is needed only to make Nim 1.2.6 happy
|
|
# Without it, the `MessageKind` type cannot be used as
|
|
# a discriminator in case objects.
|
|
unused = 0x00
|
|
|
|
ping = 0x01
|
|
pong = 0x02
|
|
findNode = 0x03
|
|
nodes = 0x04
|
|
talkReq = 0x05
|
|
talkResp = 0x06
|
|
regTopic = 0x07
|
|
ticket = 0x08
|
|
regConfirmation = 0x09
|
|
topicQuery = 0x0A
|
|
addProvider = 0x0B
|
|
getProviders = 0x0C
|
|
providers = 0x0D
|
|
addValue = 0x0E
|
|
getValue = 0x0F
|
|
respValue = 0x10
|
|
findNodeFast = 0x83
|
|
|
|
RequestId* = object
|
|
id*: seq[byte]
|
|
|
|
PingMessage* = object
|
|
sprSeq*: uint64
|
|
|
|
PongMessage* = object
|
|
sprSeq*: uint64
|
|
ip*: IpAddress
|
|
port*: uint16
|
|
|
|
FindNodeMessage* = object
|
|
distances*: seq[uint16]
|
|
|
|
FindNodeFastMessage* = object
|
|
target*: NodeId
|
|
|
|
NodesMessage* = object
|
|
total*: uint32
|
|
sprs*: seq[SignedPeerRecord]
|
|
|
|
TalkReqMessage* = object
|
|
protocol*: seq[byte]
|
|
request*: seq[byte]
|
|
|
|
TalkRespMessage* = object
|
|
response*: seq[byte]
|
|
|
|
# Not implemented, specification is not final here.
|
|
RegTopicMessage* = object
|
|
TicketMessage* = object
|
|
RegConfirmationMessage* = object
|
|
TopicQueryMessage* = object
|
|
|
|
SomeMessage* = PingMessage or PongMessage or FindNodeMessage or NodesMessage or
|
|
TalkReqMessage or TalkRespMessage or AddProviderMessage or GetProvidersMessage or
|
|
ProvidersMessage or FindNodeFastMessage or
|
|
AddValueMessage or GetValueMessage or ValueMessage
|
|
|
|
Message* = object
|
|
reqId*: RequestId
|
|
case kind*: MessageKind
|
|
of ping:
|
|
ping*: PingMessage
|
|
of pong:
|
|
pong*: PongMessage
|
|
of findNode:
|
|
findNode*: FindNodeMessage
|
|
of findNodeFast:
|
|
findNodeFast*: FindNodeFastMessage
|
|
of nodes:
|
|
nodes*: NodesMessage
|
|
of talkReq:
|
|
talkReq*: TalkReqMessage
|
|
of talkResp:
|
|
talkResp*: TalkRespMessage
|
|
of regTopic:
|
|
regtopic*: RegTopicMessage
|
|
of ticket:
|
|
ticket*: TicketMessage
|
|
of regConfirmation:
|
|
regConfirmation*: RegConfirmationMessage
|
|
of topicQuery:
|
|
topicQuery*: TopicQueryMessage
|
|
of addProvider:
|
|
addProvider*: AddProviderMessage
|
|
of getProviders:
|
|
getProviders*: GetProvidersMessage
|
|
of providers:
|
|
provs*: ProvidersMessage
|
|
of addValue:
|
|
addValue*: AddValueMessage
|
|
of getValue:
|
|
getValue*: GetValueMessage
|
|
of respValue:
|
|
value*: ValueMessage
|
|
else:
|
|
discard
|
|
|
|
template messageKind*(T: typedesc[SomeMessage]): MessageKind =
|
|
when T is PingMessage: MessageKind.ping
|
|
elif T is PongMessage: MessageKind.pong
|
|
elif T is FindNodeMessage: MessageKind.findNode
|
|
elif T is FindNodeFastMessage: MessageKind.findNodeFast
|
|
elif T is NodesMessage: MessageKind.nodes
|
|
elif T is TalkReqMessage: MessageKind.talkReq
|
|
elif T is TalkRespMessage: MessageKind.talkResp
|
|
elif T is AddProviderMessage: MessageKind.addProvider
|
|
elif T is GetProvidersMessage: MessageKind.getProviders
|
|
elif T is ProvidersMessage: MessageKind.providers
|
|
elif T is AddValueMessage: MessageKind.addValue
|
|
elif T is GetValueMessage: MessageKind.getValue
|
|
elif T is ValueMessage: MessageKind.respValue
|
|
|
|
proc hash*(reqId: RequestId): Hash =
|
|
hash(reqId.id)
|
|
|
|
proc init*(T: type RequestId, rng: var HmacDrbgContext): T =
|
|
var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes
|
|
hmacDrbgGenerate(rng, reqId.id)
|
|
reqId
|