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:
Kim De Mey 2021-09-22 11:28:04 +02:00 committed by GitHub
parent 908dc21478
commit 11c120e400
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 47 deletions

View File

@ -17,8 +17,15 @@ import
export ssz_serialization, stint export ssz_serialization, stint
const
contentKeysLimit = 64
type type
ByteList* = List[byte, 2048] ByteList* = List[byte, 2048]
Bytes2* = array[2, byte]
ContentKeysList* = List[ByteList, contentKeysLimit]
ContentKeysBitList* = BitList[contentKeysLimit]
MessageKind* = enum MessageKind* = enum
unused = 0x00 unused = 0x00
@ -29,8 +36,8 @@ type
nodes = 0x04 nodes = 0x04
findcontent = 0x05 findcontent = 0x05
foundcontent = 0x06 foundcontent = 0x06
advertise = 0x07 offer = 0x07
requestproofs = 0x08 accept = 0x08
PingMessage* = object PingMessage* = object
enrSeq*: uint64 enrSeq*: uint64
@ -55,15 +62,12 @@ type
enrs*: List[ByteList, 32] enrs*: List[ByteList, 32]
payload*: ByteList payload*: ByteList
AdvertiseMessage* = List[ByteList, 32] # No container, heh... OfferMessage* = object
contentKeys*: ContentKeysList
# This would be more consistent with the other messages AcceptMessage* = object
# AdvertiseMessage* = object connectionId*: Bytes2
# contentKeys*: List[ByteList, 32] contentKeys*: ContentKeysBitList
RequestProofsMessage* = object
connectionId*: List[byte, 4]
contentKeys*: List[ByteList, 32]
Message* = object Message* = object
case kind*: MessageKind case kind*: MessageKind
@ -79,10 +83,10 @@ type
findcontent*: FindContentMessage findcontent*: FindContentMessage
of foundcontent: of foundcontent:
foundcontent*: FoundContentMessage foundcontent*: FoundContentMessage
of advertise: of offer:
advertise*: AdvertiseMessage offer*: OfferMessage
of requestproofs: of accept:
requestproofs*: RequestProofsMessage accept*: AcceptMessage
else: else:
discard discard
@ -90,7 +94,7 @@ type
PingMessage or PongMessage or PingMessage or PongMessage or
FindNodeMessage or NodesMessage or FindNodeMessage or NodesMessage or
FindContentMessage or FoundContentMessage or FindContentMessage or FoundContentMessage or
AdvertiseMessage or RequestProofsMessage OfferMessage or AcceptMessage
template messageKind*(T: typedesc[SomeMessage]): MessageKind = template messageKind*(T: typedesc[SomeMessage]): MessageKind =
when T is PingMessage: ping when T is PingMessage: ping
@ -99,8 +103,8 @@ template messageKind*(T: typedesc[SomeMessage]): MessageKind =
elif T is NodesMessage: nodes elif T is NodesMessage: nodes
elif T is FindContentMessage: findcontent elif T is FindContentMessage: findcontent
elif T is FoundContentMessage: foundcontent elif T is FoundContentMessage: foundcontent
elif T is AdvertiseMessage: advertise elif T is OfferMessage: offer
elif T is RequestProofsMessage: requestproofs elif T is AcceptMessage: accept
template toSszType*(x: UInt256): array[32, byte] = template toSszType*(x: UInt256): array[32, byte] =
toBytesLE(x) toBytesLE(x)
@ -144,10 +148,10 @@ proc decodeMessage*(body: openarray[byte]): Result[Message, cstring] =
message.findcontent = SSZ.decode(body.toOpenArray(1, body.high), FindContentMessage) message.findcontent = SSZ.decode(body.toOpenArray(1, body.high), FindContentMessage)
of foundcontent: of foundcontent:
message.foundcontent = SSZ.decode(body.toOpenArray(1, body.high), FoundContentMessage) message.foundcontent = SSZ.decode(body.toOpenArray(1, body.high), FoundContentMessage)
of advertise: of offer:
message.advertise = SSZ.decode(body.toOpenArray(1, body.high), AdvertiseMessage) message.offer = SSZ.decode(body.toOpenArray(1, body.high), OfferMessage)
of requestproofs: of accept:
message.requestproofs = SSZ.decode(body.toOpenArray(1, body.high), RequestProofsMessage) message.accept = SSZ.decode(body.toOpenArray(1, body.high), AcceptMessage)
except SszError: except SszError:
return err("Invalid message encoding") return err("Invalid message encoding")

View File

@ -143,13 +143,17 @@ proc handleFindContent(p: PortalProtocol, fc: FindContentMessage): seq[byte] =
encodeMessage(FoundContentMessage( encodeMessage(FoundContentMessage(
enrs: enrs, payload: content)) enrs: enrs, payload: content))
proc handleAdvertise(p: PortalProtocol, a: AdvertiseMessage): seq[byte] = proc handleOffer(p: PortalProtocol, a: OfferMessage): seq[byte] =
# TODO: Not implemented
let let
connectionId = List[byte, 4](@[]) # TODO: Random ID that needs to be stored together with some buffer that
contentKeys = List[ByteList, 32](@[]) # gets shared with uTP session that needs to be set up (start listening)
encodeMessage(RequestProofsMessage(connectionId: connectionId, connectionId = Bytes2([byte 0x01, 0x02])
contentKeys: contentKeys)) # 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], proc messageHandler*(protocol: TalkProtocol, request: seq[byte],
srcId: NodeId, srcUdpAddress: Address): seq[byte] = srcId: NodeId, srcUdpAddress: Address): seq[byte] =
@ -168,8 +172,8 @@ proc messageHandler*(protocol: TalkProtocol, request: seq[byte],
p.handleFindNode(message.findNode) p.handleFindNode(message.findNode)
of MessageKind.findcontent: of MessageKind.findcontent:
p.handleFindContent(message.findcontent) p.handleFindContent(message.findcontent)
of MessageKind.advertise: of MessageKind.offer:
p.handleAdvertise(message.advertise) p.handleOffer(message.offer)
else: else:
@[] @[]
else: else:
@ -242,6 +246,19 @@ proc findContent*(p: PortalProtocol, dst: Node, contentKey: ByteList):
return await reqResponse[FindContentMessage, FoundContentMessage]( return await reqResponse[FindContentMessage, FoundContentMessage](
p, dst, PortalProtocolId, fc) 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] = proc recordsFromBytes(rawRecords: List[ByteList, 32]): seq[Record] =
var records: seq[Record] var records: seq[Record]
for r in rawRecords.asSeq(): for r in rawRecords.asSeq():

View File

@ -185,3 +185,16 @@ procSuite "Portal Tests":
await test.stopTest() 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()

View File

@ -165,41 +165,37 @@ suite "Portal Protocol Message Encodings":
message.foundcontent.enrs[1] == ByteList(e2.raw) message.foundcontent.enrs[1] == ByteList(e2.raw)
message.foundcontent.payload == payload message.foundcontent.payload == payload
test "Advertise Request": test "Offer Request":
let let
contentKeys = List[ByteList, 32](List(@[ByteList(@[byte 0x01, 0x02, 0x03])])) contentKeys = ContentKeysList(List(@[ByteList(@[byte 0x01, 0x02, 0x03])]))
am = AdvertiseMessage(contentKeys) am = OfferMessage(contentKeys: contentKeys)
# am = AdvertiseMessage(contentKeys: contentKeys)
let encoded = encodeMessage(am) let encoded = encodeMessage(am)
check encoded.toHex == "0704000000010203" check encoded.toHex == "070400000004000000010203"
# "070400000004000000010203"
let decoded = decodeMessage(encoded) let decoded = decodeMessage(encoded)
check decoded.isOk() check decoded.isOk()
let message = decoded.get() let message = decoded.get()
check: check:
message.kind == advertise message.kind == offer
message.advertise == contentKeys message.offer.contentKeys == contentKeys
# message.advertise.contentKeys == contentKeys
test "RequestProofs Response": # That sounds weird test "Accept Response":
let let
connectionId = List[byte, 4](@[byte 0x01, 0x02, 0x03, 0x04]) connectionId = Bytes2([byte 0x01, 0x02])
contentKeys = contentKeys = ContentKeysBitList.init(8)
List[ByteList, 32](List(@[ByteList(@[byte 0x01, 0x02, 0x03])])) n = AcceptMessage(connectionId: connectionId,
n = RequestProofsMessage(connectionId: connectionId,
contentKeys: contentKeys) contentKeys: contentKeys)
let encoded = encodeMessage(n) let encoded = encodeMessage(n)
check encoded.toHex == "08080000000c0000000102030404000000010203" check encoded.toHex == "080102060000000001"
let decoded = decodeMessage(encoded) let decoded = decodeMessage(encoded)
check decoded.isOk() check decoded.isOk()
let message = decoded.get() let message = decoded.get()
check: check:
message.kind == requestproofs message.kind == MessageKind.accept
message.requestproofs.connectionId == connectionId message.accept.connectionId == connectionId
message.requestproofs.contentKeys == contentKeys message.accept.contentKeys == contentKeys