mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-25 03:28:57 +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
|
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")
|
||||||
|
|
||||||
|
@ -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():
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user