mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-24 19:19:21 +00:00
Update wire protocol of state network spec (#829)
* Update wire protocol of state network spec * BytesN should be SSZ Vector not List * Add specific lists and bitlists for content keys
This commit is contained in:
parent
908dc21478
commit
11c120e400
@ -17,8 +17,15 @@ import
|
||||
|
||||
export ssz_serialization, stint
|
||||
|
||||
const
|
||||
contentKeysLimit = 64
|
||||
|
||||
type
|
||||
ByteList* = List[byte, 2048]
|
||||
Bytes2* = array[2, byte]
|
||||
|
||||
ContentKeysList* = List[ByteList, contentKeysLimit]
|
||||
ContentKeysBitList* = BitList[contentKeysLimit]
|
||||
|
||||
MessageKind* = enum
|
||||
unused = 0x00
|
||||
@ -29,8 +36,8 @@ type
|
||||
nodes = 0x04
|
||||
findcontent = 0x05
|
||||
foundcontent = 0x06
|
||||
advertise = 0x07
|
||||
requestproofs = 0x08
|
||||
offer = 0x07
|
||||
accept = 0x08
|
||||
|
||||
PingMessage* = object
|
||||
enrSeq*: uint64
|
||||
@ -55,15 +62,12 @@ type
|
||||
enrs*: List[ByteList, 32]
|
||||
payload*: ByteList
|
||||
|
||||
AdvertiseMessage* = List[ByteList, 32] # No container, heh...
|
||||
OfferMessage* = object
|
||||
contentKeys*: ContentKeysList
|
||||
|
||||
# This would be more consistent with the other messages
|
||||
# AdvertiseMessage* = object
|
||||
# contentKeys*: List[ByteList, 32]
|
||||
|
||||
RequestProofsMessage* = object
|
||||
connectionId*: List[byte, 4]
|
||||
contentKeys*: List[ByteList, 32]
|
||||
AcceptMessage* = object
|
||||
connectionId*: Bytes2
|
||||
contentKeys*: ContentKeysBitList
|
||||
|
||||
Message* = object
|
||||
case kind*: MessageKind
|
||||
@ -79,10 +83,10 @@ type
|
||||
findcontent*: FindContentMessage
|
||||
of foundcontent:
|
||||
foundcontent*: FoundContentMessage
|
||||
of advertise:
|
||||
advertise*: AdvertiseMessage
|
||||
of requestproofs:
|
||||
requestproofs*: RequestProofsMessage
|
||||
of offer:
|
||||
offer*: OfferMessage
|
||||
of accept:
|
||||
accept*: AcceptMessage
|
||||
else:
|
||||
discard
|
||||
|
||||
@ -90,7 +94,7 @@ type
|
||||
PingMessage or PongMessage or
|
||||
FindNodeMessage or NodesMessage or
|
||||
FindContentMessage or FoundContentMessage or
|
||||
AdvertiseMessage or RequestProofsMessage
|
||||
OfferMessage or AcceptMessage
|
||||
|
||||
template messageKind*(T: typedesc[SomeMessage]): MessageKind =
|
||||
when T is PingMessage: ping
|
||||
@ -99,8 +103,8 @@ template messageKind*(T: typedesc[SomeMessage]): MessageKind =
|
||||
elif T is NodesMessage: nodes
|
||||
elif T is FindContentMessage: findcontent
|
||||
elif T is FoundContentMessage: foundcontent
|
||||
elif T is AdvertiseMessage: advertise
|
||||
elif T is RequestProofsMessage: requestproofs
|
||||
elif T is OfferMessage: offer
|
||||
elif T is AcceptMessage: accept
|
||||
|
||||
template toSszType*(x: UInt256): array[32, byte] =
|
||||
toBytesLE(x)
|
||||
@ -144,10 +148,10 @@ proc decodeMessage*(body: openarray[byte]): Result[Message, cstring] =
|
||||
message.findcontent = SSZ.decode(body.toOpenArray(1, body.high), FindContentMessage)
|
||||
of foundcontent:
|
||||
message.foundcontent = SSZ.decode(body.toOpenArray(1, body.high), FoundContentMessage)
|
||||
of advertise:
|
||||
message.advertise = SSZ.decode(body.toOpenArray(1, body.high), AdvertiseMessage)
|
||||
of requestproofs:
|
||||
message.requestproofs = SSZ.decode(body.toOpenArray(1, body.high), RequestProofsMessage)
|
||||
of offer:
|
||||
message.offer = SSZ.decode(body.toOpenArray(1, body.high), OfferMessage)
|
||||
of accept:
|
||||
message.accept = SSZ.decode(body.toOpenArray(1, body.high), AcceptMessage)
|
||||
except SszError:
|
||||
return err("Invalid message encoding")
|
||||
|
||||
|
@ -143,13 +143,17 @@ proc handleFindContent(p: PortalProtocol, fc: FindContentMessage): seq[byte] =
|
||||
encodeMessage(FoundContentMessage(
|
||||
enrs: enrs, payload: content))
|
||||
|
||||
proc handleAdvertise(p: PortalProtocol, a: AdvertiseMessage): seq[byte] =
|
||||
# TODO: Not implemented
|
||||
proc handleOffer(p: PortalProtocol, a: OfferMessage): seq[byte] =
|
||||
let
|
||||
connectionId = List[byte, 4](@[])
|
||||
contentKeys = List[ByteList, 32](@[])
|
||||
encodeMessage(RequestProofsMessage(connectionId: connectionId,
|
||||
contentKeys: contentKeys))
|
||||
# TODO: Random ID that needs to be stored together with some buffer that
|
||||
# gets shared with uTP session that needs to be set up (start listening)
|
||||
connectionId = Bytes2([byte 0x01, 0x02])
|
||||
# TODO: Not implemented: Based on the content radius and the content that is
|
||||
# already stored, interest in provided content keys needs to be indicated
|
||||
# by setting bits in this BitList
|
||||
contentKeys = ContentKeysBitList.init(a.contentKeys.len)
|
||||
encodeMessage(
|
||||
AcceptMessage(connectionId: connectionId, contentKeys: contentKeys))
|
||||
|
||||
proc messageHandler*(protocol: TalkProtocol, request: seq[byte],
|
||||
srcId: NodeId, srcUdpAddress: Address): seq[byte] =
|
||||
@ -168,8 +172,8 @@ proc messageHandler*(protocol: TalkProtocol, request: seq[byte],
|
||||
p.handleFindNode(message.findNode)
|
||||
of MessageKind.findcontent:
|
||||
p.handleFindContent(message.findcontent)
|
||||
of MessageKind.advertise:
|
||||
p.handleAdvertise(message.advertise)
|
||||
of MessageKind.offer:
|
||||
p.handleOffer(message.offer)
|
||||
else:
|
||||
@[]
|
||||
else:
|
||||
@ -242,6 +246,19 @@ proc findContent*(p: PortalProtocol, dst: Node, contentKey: ByteList):
|
||||
return await reqResponse[FindContentMessage, FoundContentMessage](
|
||||
p, dst, PortalProtocolId, fc)
|
||||
|
||||
proc offer*(p: PortalProtocol, dst: Node, contentKeys: ContentKeysList):
|
||||
Future[PortalResult[AcceptMessage]] {.async.} =
|
||||
let offer = OfferMessage(contentKeys: contentKeys)
|
||||
|
||||
trace "Send message request", dstId = dst.id, kind = MessageKind.offer
|
||||
|
||||
return await reqResponse[OfferMessage, AcceptMessage](
|
||||
p, dst, PortalProtocolId, offer)
|
||||
|
||||
# TODO: Actually have to parse the offer message and get the uTP connection
|
||||
# id, and initiate an uTP stream with given uTP connection id to get the data
|
||||
# out.
|
||||
|
||||
proc recordsFromBytes(rawRecords: List[ByteList, 32]): seq[Record] =
|
||||
var records: seq[Record]
|
||||
for r in rawRecords.asSeq():
|
||||
|
@ -185,3 +185,16 @@ procSuite "Portal Tests":
|
||||
|
||||
await test.stopTest()
|
||||
|
||||
asyncTest "Portal Offer/Accept":
|
||||
let test = defaultTestCase(rng)
|
||||
let contentKeys = ContentKeysList(List(@[ByteList(@[byte 0x01, 0x02, 0x03])]))
|
||||
|
||||
let accept = await test.proto1.offer(
|
||||
test.proto2.baseProtocol.localNode, contentKeys)
|
||||
|
||||
check:
|
||||
accept.isOk()
|
||||
accept.get().connectionId.len == 2
|
||||
accept.get().contentKeys.len == contentKeys.len
|
||||
|
||||
await test.stopTest()
|
||||
|
@ -165,41 +165,37 @@ suite "Portal Protocol Message Encodings":
|
||||
message.foundcontent.enrs[1] == ByteList(e2.raw)
|
||||
message.foundcontent.payload == payload
|
||||
|
||||
test "Advertise Request":
|
||||
test "Offer Request":
|
||||
let
|
||||
contentKeys = List[ByteList, 32](List(@[ByteList(@[byte 0x01, 0x02, 0x03])]))
|
||||
am = AdvertiseMessage(contentKeys)
|
||||
# am = AdvertiseMessage(contentKeys: contentKeys)
|
||||
contentKeys = ContentKeysList(List(@[ByteList(@[byte 0x01, 0x02, 0x03])]))
|
||||
am = OfferMessage(contentKeys: contentKeys)
|
||||
|
||||
let encoded = encodeMessage(am)
|
||||
check encoded.toHex == "0704000000010203"
|
||||
# "070400000004000000010203"
|
||||
check encoded.toHex == "070400000004000000010203"
|
||||
|
||||
let decoded = decodeMessage(encoded)
|
||||
check decoded.isOk()
|
||||
|
||||
let message = decoded.get()
|
||||
check:
|
||||
message.kind == advertise
|
||||
message.advertise == contentKeys
|
||||
# message.advertise.contentKeys == contentKeys
|
||||
message.kind == offer
|
||||
message.offer.contentKeys == contentKeys
|
||||
|
||||
test "RequestProofs Response": # That sounds weird
|
||||
test "Accept Response":
|
||||
let
|
||||
connectionId = List[byte, 4](@[byte 0x01, 0x02, 0x03, 0x04])
|
||||
contentKeys =
|
||||
List[ByteList, 32](List(@[ByteList(@[byte 0x01, 0x02, 0x03])]))
|
||||
n = RequestProofsMessage(connectionId: connectionId,
|
||||
connectionId = Bytes2([byte 0x01, 0x02])
|
||||
contentKeys = ContentKeysBitList.init(8)
|
||||
n = AcceptMessage(connectionId: connectionId,
|
||||
contentKeys: contentKeys)
|
||||
|
||||
let encoded = encodeMessage(n)
|
||||
check encoded.toHex == "08080000000c0000000102030404000000010203"
|
||||
check encoded.toHex == "080102060000000001"
|
||||
|
||||
let decoded = decodeMessage(encoded)
|
||||
check decoded.isOk()
|
||||
|
||||
let message = decoded.get()
|
||||
check:
|
||||
message.kind == requestproofs
|
||||
message.requestproofs.connectionId == connectionId
|
||||
message.requestproofs.contentKeys == contentKeys
|
||||
message.kind == MessageKind.accept
|
||||
message.accept.connectionId == connectionId
|
||||
message.accept.contentKeys == contentKeys
|
||||
|
Loading…
x
Reference in New Issue
Block a user