mirror of https://github.com/status-im/nim-eth.git
Introduce enr.TypedRecord that can replace enr.Record in the future
This commit is contained in:
parent
39857d57f0
commit
988d743c9a
|
@ -1,4 +1,4 @@
|
||||||
import strutils, macros, algorithm
|
import strutils, macros, algorithm, options
|
||||||
import eth/[rlp, keys], nimcrypto, stew/base64
|
import eth/[rlp, keys], nimcrypto, stew/base64
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -10,6 +10,16 @@ type
|
||||||
|
|
||||||
EnrUri* = distinct string
|
EnrUri* = distinct string
|
||||||
|
|
||||||
|
TypedRecord* = object
|
||||||
|
id*: string
|
||||||
|
secp256k1*: Option[array[33, byte]]
|
||||||
|
ip*: Option[array[4, byte]]
|
||||||
|
ip6*: Option[array[16, byte]]
|
||||||
|
tcp*: Option[int]
|
||||||
|
udp*: Option[int]
|
||||||
|
tcp6*: Option[int]
|
||||||
|
udp6*: Option[int]
|
||||||
|
|
||||||
FieldKind = enum
|
FieldKind = enum
|
||||||
kString,
|
kString,
|
||||||
kNum,
|
kNum,
|
||||||
|
@ -91,18 +101,28 @@ proc requireKind(f: Field, kind: FieldKind) =
|
||||||
if f.kind != kind:
|
if f.kind != kind:
|
||||||
raise newException(ValueError, "Wrong field kind")
|
raise newException(ValueError, "Wrong field kind")
|
||||||
|
|
||||||
proc get*[T: seq[byte] | string | SomeInteger](r: Record, key: string, typ: typedesc[T]): typ =
|
proc get*(r: Record, key: string, T: type): T =
|
||||||
var f: Field
|
var f: Field
|
||||||
if r.getField(key, f):
|
if r.getField(key, f):
|
||||||
when typ is SomeInteger:
|
when T is SomeInteger:
|
||||||
requireKind(f, kNum)
|
requireKind(f, kNum)
|
||||||
return typ(f.num)
|
return T(f.num)
|
||||||
elif typ is seq[byte]:
|
elif T is seq[byte]:
|
||||||
requireKind(f, kBytes)
|
requireKind(f, kBytes)
|
||||||
return f.bytes
|
return f.bytes
|
||||||
elif typ is string:
|
elif T is string:
|
||||||
requireKind(f, kString)
|
requireKind(f, kString)
|
||||||
return f.str
|
return f.str
|
||||||
|
elif T is array:
|
||||||
|
when type(result[0]) is byte:
|
||||||
|
requireKind(f, kBytes)
|
||||||
|
if f.bytes.len != result.len:
|
||||||
|
raise newException(ValueError, "Invalid byte blob length")
|
||||||
|
copyMem(addr result[0], addr f.bytes[0], result.len)
|
||||||
|
else:
|
||||||
|
{.fatal: "Unsupported output type in enr.get".}
|
||||||
|
else:
|
||||||
|
{.fatal: "Unsupported output type in enr.get".}
|
||||||
else:
|
else:
|
||||||
raise newException(KeyError, "Key not found in ENR: " & key)
|
raise newException(KeyError, "Key not found in ENR: " & key)
|
||||||
|
|
||||||
|
@ -111,6 +131,31 @@ proc get*(r: Record, pubKey: var PublicKey): bool =
|
||||||
if r.getField("secp256k1", pubkeyField) and pubkeyField.kind == kBytes:
|
if r.getField("secp256k1", pubkeyField) and pubkeyField.kind == kBytes:
|
||||||
result = recoverPublicKey(pubkeyField.bytes, pubKey) == EthKeysStatus.Success
|
result = recoverPublicKey(pubkeyField.bytes, pubKey) == EthKeysStatus.Success
|
||||||
|
|
||||||
|
proc tryGet*(r: Record, key: string, T: type): Option[T] =
|
||||||
|
try:
|
||||||
|
return some r.get(key, T)
|
||||||
|
except CatchableError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
func toTypedRecord*(r: Record): Option[TypedRecord] =
|
||||||
|
let id = r.tryGet("id", string)
|
||||||
|
if id.isSome:
|
||||||
|
var tr: TypedRecord
|
||||||
|
tr.id = id.get
|
||||||
|
|
||||||
|
template readField(fieldName: untyped) {.dirty.} =
|
||||||
|
tr.fieldName = tryGet(r, astToStr(fieldName), type(tr.fieldName.get))
|
||||||
|
|
||||||
|
readField secp256k1
|
||||||
|
readField ip
|
||||||
|
readField ip6
|
||||||
|
readField tcp
|
||||||
|
readField tcp6
|
||||||
|
readField udp
|
||||||
|
readField udp6
|
||||||
|
|
||||||
|
return some(tr)
|
||||||
|
|
||||||
proc verifySignatureV4(r: Record, sigData: openarray[byte], content: seq[byte]): bool =
|
proc verifySignatureV4(r: Record, sigData: openarray[byte], content: seq[byte]): bool =
|
||||||
var publicKey: PublicKey
|
var publicKey: PublicKey
|
||||||
if r.get(publicKey):
|
if r.get(publicKey):
|
||||||
|
|
Loading…
Reference in New Issue