NagyZoltanPeter 0a7f16a332
chore: rate limit peer exchange protocol, enhanced response status in RPC (#3035)
* Enhanced peer-ex protocol - added rate limiting, added response status and desc to the rpc

* Better error result handling for PeerEx request, adjusted tests

* Refactored RateLimit configuration option for better CLI UX - now possible to set separate limits per protocol. Adjusted mountings. Added and adjusted tests

* Fix libwaku due to changes of error return type of fetchPeerExchangePeers

* Fix rate limit setting tests due to changed defaults

* Introduce new gauge to help dasboard effectively show current rate limit applied for protocol

* Adjust timeing in filter rate limit test to let macos CI test run ok.

* Address review findings, namings, error logs, removed left-overs

* Changes to reflect latest spec agreement and changes. PeerExchange RPC is changed the now respond structure will contain status_code and status_desc.
2024-09-18 15:58:07 +02:00

111 lines
2.7 KiB
Nim

{.push raises: [].}
import std/options
import ../common/protobuf, ./rpc
proc encode*(rpc: PeerExchangeRequest): ProtoBuffer =
var pb = initProtoBuffer()
pb.write3(1, rpc.numPeers)
pb.finish3()
pb
proc decode*(T: type PeerExchangeRequest, buffer: seq[byte]): ProtoResult[T] =
let pb = initProtoBuffer(buffer)
var rpc = PeerExchangeRequest(numPeers: 0)
var numPeers: uint64
if ?pb.getField(1, numPeers):
rpc.numPeers = numPeers
ok(rpc)
proc encode*(rpc: PeerExchangePeerInfo): ProtoBuffer =
var pb = initProtoBuffer()
pb.write3(1, rpc.enr)
pb.finish3()
pb
proc decode*(T: type PeerExchangePeerInfo, buffer: seq[byte]): ProtoResult[T] =
let pb = initProtoBuffer(buffer)
var rpc = PeerExchangePeerInfo(enr: @[])
var peerInfoBuffer: seq[byte]
if ?pb.getField(1, peerInfoBuffer):
rpc.enr = peerInfoBuffer
ok(rpc)
proc parse*(T: type PeerExchangeResponseStatusCode, status: uint32): T =
case status
of 200, 400, 429, 503:
PeerExchangeResponseStatusCode(status)
else:
PeerExchangeResponseStatusCode.UNKNOWN
proc encode*(rpc: PeerExchangeResponse): ProtoBuffer =
var pb = initProtoBuffer()
for pi in rpc.peerInfos:
pb.write3(1, pi.encode())
pb.write3(10, rpc.status_code.uint32)
pb.write3(11, rpc.status_desc)
pb.finish3()
pb
proc decode*(T: type PeerExchangeResponse, buffer: seq[byte]): ProtobufResult[T] =
let pb = initProtoBuffer(buffer)
var rpc = PeerExchangeResponse(peerInfos: @[])
var peerInfoBuffers: seq[seq[byte]]
if ?pb.getRepeatedField(1, peerInfoBuffers):
for pib in peerInfoBuffers:
rpc.peerInfos.add(?PeerExchangePeerInfo.decode(pib))
var status_code: uint32
if ?pb.getField(10, status_code):
rpc.status_code = PeerExchangeResponseStatusCode.parse(status_code)
else:
return err(ProtobufError.missingRequiredField("status_code"))
var status_desc: string
if ?pb.getField(11, status_desc):
rpc.status_desc = some(status_desc)
else:
rpc.status_desc = none(string)
ok(rpc)
proc encode*(rpc: PeerExchangeRpc): ProtoBuffer =
var pb = initProtoBuffer()
pb.write3(1, rpc.request.encode())
pb.write3(2, rpc.response.encode())
pb.finish3()
pb
proc decode*(T: type PeerExchangeRpc, buffer: seq[byte]): ProtobufResult[T] =
let pb = initProtoBuffer(buffer)
var rpc = PeerExchangeRpc()
var requestBuffer: seq[byte]
if not ?pb.getField(1, requestBuffer):
return err(ProtobufError.missingRequiredField("request"))
rpc.request = ?PeerExchangeRequest.decode(requestBuffer)
var responseBuffer: seq[byte]
if not ?pb.getField(2, responseBuffer):
return err(ProtobufError.missingRequiredField("response"))
rpc.response = ?PeerExchangeResponse.decode(responseBuffer)
ok(rpc)