mirror of https://github.com/status-im/nim-eth.git
Enr rlp lists (#408)
* Don't fail ENR decoding when value is an RLP list * Store RLP raw list in the ENR field pair instead * Add ENR kList FieldKind so lists can be treated differently Treated differently now when printing out the ENR, mentioning that it is a raw RLP list
This commit is contained in:
parent
6fbf129ba9
commit
f101c83626
|
@ -46,7 +46,8 @@ type
|
|||
FieldKind = enum
|
||||
kString,
|
||||
kNum,
|
||||
kBytes
|
||||
kBytes,
|
||||
kList
|
||||
|
||||
Field = object
|
||||
case kind: FieldKind
|
||||
|
@ -56,6 +57,9 @@ type
|
|||
num: BiggestUInt
|
||||
of kBytes:
|
||||
bytes: seq[byte]
|
||||
of kList:
|
||||
listRaw: seq[byte] ## Differently from the other kinds, this is is stored
|
||||
## as raw (encoded) RLP data, and thus treated as such further on.
|
||||
|
||||
EnrResult*[T] = Result[T, cstring]
|
||||
|
||||
|
@ -68,6 +72,8 @@ template toField[T](v: T): Field =
|
|||
Field(kind: kBytes, bytes: v)
|
||||
elif T is SomeUnsignedInt:
|
||||
Field(kind: kNum, num: BiggestUInt(v))
|
||||
elif T is object|tuple:
|
||||
Field(kind: kList, listRaw: rlp.encode(v))
|
||||
else:
|
||||
{.error: "Unsupported field type".}
|
||||
|
||||
|
@ -80,6 +86,8 @@ proc `==`(a, b: Field): bool =
|
|||
return a.num == b.num
|
||||
of kBytes:
|
||||
return a.bytes == b.bytes
|
||||
of kList:
|
||||
return a.listRaw == b.listRaw
|
||||
else:
|
||||
return false
|
||||
|
||||
|
@ -96,6 +104,7 @@ proc makeEnrRaw(seqNum: uint64, pk: PrivateKey,
|
|||
of kString: w.append(v.str)
|
||||
of kNum: w.append(v.num)
|
||||
of kBytes: w.append(v.bytes)
|
||||
of kList: w.appendRawBytes(v.listRaw) # No encoding needs to happen
|
||||
w.finish()
|
||||
|
||||
let toSign = block:
|
||||
|
@ -419,7 +428,16 @@ proc fromBytesAux(r: var Record): bool {.raises: [RlpError, Defect].} =
|
|||
let v = rlp.read(uint16)
|
||||
r.pairs.add((k, Field(kind: kNum, num: v)))
|
||||
else:
|
||||
# Don't know really what this is supposed to represent so drop it in
|
||||
# `kBytes` field pair when a single byte or blob.
|
||||
if rlp.isSingleByte() or rlp.isBlob():
|
||||
r.pairs.add((k, Field(kind: kBytes, bytes: rlp.read(seq[byte]))))
|
||||
elif rlp.isList():
|
||||
# Not supporting decoding lists as value (especially unknown ones),
|
||||
# just drop the raw RLP value in there.
|
||||
r.pairs.add((k, Field(kind: kList, listRaw: @(rlp.rawData()))))
|
||||
# Need to skip the element still.
|
||||
rlp.skipElem()
|
||||
|
||||
verifySignature(r)
|
||||
|
||||
|
@ -463,6 +481,8 @@ proc `$`(f: Field): string =
|
|||
"0x" & f.bytes.toHex
|
||||
of kString:
|
||||
"\"" & f.str & "\""
|
||||
of kList:
|
||||
"(Raw RLP list) " & "0x" & f.listRaw.toHex
|
||||
|
||||
proc `$`*(r: Record): string =
|
||||
result = "("
|
||||
|
|
|
@ -37,7 +37,7 @@ suite "ENR":
|
|||
var r: Record
|
||||
check not fromBytes(r, [])
|
||||
|
||||
test "Base64 dserialsation without data":
|
||||
test "Base64 deserialsation without data":
|
||||
var r: Record
|
||||
let sigValid = r.fromURI("enr:")
|
||||
check(not sigValid)
|
||||
|
@ -243,3 +243,25 @@ suite "ENR":
|
|||
typedEnr.udp.get() == 9001
|
||||
|
||||
r.seqNum == 4
|
||||
|
||||
test "ENR with RLP list value":
|
||||
type
|
||||
RlpTestList = object
|
||||
number: uint16
|
||||
data: seq[byte]
|
||||
text: string
|
||||
|
||||
let rlpList =
|
||||
RlpTestList(number: 72, data: @[byte 0x0, 0x1, 0x2], text: "Hi there")
|
||||
|
||||
let pk = PrivateKey.fromHex(
|
||||
"5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d")[]
|
||||
var r = initRecord(123, pk, {"udp": 1234'u, "ip": [byte 5, 6, 7, 8],
|
||||
"some_list": rlpList})[]
|
||||
|
||||
check($r == """(123, id: "v4", ip: 0x05060708, secp256k1: 0x02E51EFA66628CE09F689BC2B82F165A75A9DDECBB6A804BE15AC3FDF41F3B34E7, some_list: (Raw RLP list) 0xCE4883000102884869207468657265, udp: 1234)""")
|
||||
|
||||
let encoded = rlp.encode(r)
|
||||
let decoded = rlp.decode(encoded, enr.Record)
|
||||
check($decoded == $r)
|
||||
check(decoded.raw == r.raw)
|
||||
|
|
Loading…
Reference in New Issue