Add discv5 constants to know allowed max talkresp message size (#732)

This commit is contained in:
Kim De Mey 2024-09-19 17:53:11 +02:00 committed by GitHub
parent 4eecab27ef
commit aa1e738a97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 1 deletions

View File

@ -55,6 +55,22 @@ const
# the UDP payload and the UDP header is not taken into account.
# https://github.com/ethereum/devp2p/blob/26e380b1f3a57db16fbdd4528dde82104c77fa38/discv5/discv5-wire.md#udp-communication
maxDiscv5PacketSize* = 1280
# Following constants can be used to calculate the overhead of a packet and
# thus the maximum size of a payload that can be sent over talkresp.
discv5OrdinaryPacketOverhead* = # total 87 bytes
16 + # IV size
55 + # header size
16 # HMAC
# talkResp message = msgId + rlp: [request-id, response]
discv5TalkRespOverhead* = # total 16 bytes
1 + # talkResp msg id
3 + # rlp encoding outer list, max length will be encoded in 2 bytes
9 + # request id (max = 8) + 1 byte from rlp encoding byte string
3 # rlp encoding response byte string, max length in 2 bytes
# TalkResp message is a response message so the session is established and a
# ordinary discv5 packet is used for size calculation.
maxDiscv5TalkRespPayload* = maxDiscv5PacketSize - discv5OrdinaryPacketOverhead -
discv5TalkRespOverhead
type
AESGCMNonce* = array[gcmNonceSize, byte]

View File

@ -89,7 +89,7 @@ import
ip_vote, nodes_verification]
export
results, node, enr, encoding.maxDiscv5PacketSize
results, node, enr, encoding.maxDiscv5PacketSize, encoding.maxDiscv5TalkRespPayload
declareCounter discovery_message_requests_outgoing,
"Discovery protocol outgoing message requests", labels = ["response"]

View File

@ -158,6 +158,24 @@ suite "Discovery v5.1 Protocol Message Encodings":
message.kind == talkResp
message.talkResp.response == "hi".toBytes()
test "Talk Response Payload limit":
let
payload = repeat(5.byte, maxDiscv5TalkRespPayload)
tr = TalkRespMessage(response: payload)
reqId = RequestId(id: @[1.byte, 2, 3, 4, 5, 6, 7, 8]) # max requestId = 8 bytes
let encoded = encodeMessage(tr, reqId)
check encoded.len() == maxDiscv5TalkRespPayload + discv5TalkRespOverhead
let decoded = decodeMessage(encoded)
check decoded.isOk()
let message = decoded.get()
check:
message.reqId == reqId
message.kind == talkResp
message.talkResp.response == payload
test "Ping with too large RequestId":
let
enrSeq = 1'u64
@ -626,3 +644,30 @@ suite "Discovery v5.1 Additional Encode/Decode":
decoded.get().messageOpt.get().kind == ping
decoded.get().messageOpt.get().ping.enrSeq == 0
decoded[].requestNonce == nonce
test "Encode / Decode Ordinary Message Packet - TalkResp Payload limit":
let
payload = repeat(5.byte, maxDiscv5TalkRespPayload)
m = TalkRespMessage(response: payload)
reqId = RequestId.init(rng[])
message = encodeMessage(m, reqId)
# Need to manually add the secrets that normally get negotiated in the
# handshake packet.
var secrets: HandshakeSecrets
codecA.sessions.store(nodeB.id, nodeB.address.get(), secrets.recipientKey,
secrets.initiatorKey)
codecB.sessions.store(nodeA.id, nodeA.address.get(), secrets.initiatorKey,
secrets.recipientKey)
let (data, nonce) = encodeMessagePacket(rng[], codecA, nodeB.id,
nodeB.address.get(), message)
check data.len() == maxDiscv5PacketSize
let decoded = codecB.decodePacket(nodeA.address.get(), data)
check:
decoded.isOk()
decoded[].flag == OrdinaryMessage
decoded[].messageOpt.isSome()
decoded[].requestNonce == nonce