clean up peerid (#470)

* fix dangling cstring on error return
* remove some useless inlines
* less mallocs in shortlog
* proc -> func
* rename test
This commit is contained in:
Jacek Sieka 2020-12-03 20:53:16 +01:00 committed by GitHub
parent e9d4679059
commit 1befeb8c2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 62 deletions

View File

@ -11,20 +11,19 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import std/hashes import
import chronicles std/[hashes, strutils],
import nimcrypto/utils, stew/base58 stew/[base58, results],
import crypto/crypto, multicodec, multihash, vbuffer chronicles,
import protobuf/minprotobuf nimcrypto/utils,
import stew/results ./crypto/crypto, ./multicodec, ./multihash, ./vbuffer,
./protobuf/minprotobuf
export results export results
const const
maxInlineKeyLength* = 42 maxInlineKeyLength* = 42
# TODO: add proper on disc serialization
# using peer-id protobuf format
type type
PeerID* = object PeerID* = object
data*: seq[byte] data*: seq[byte]
@ -36,19 +35,15 @@ func `$`*(pid: PeerID): string =
func shortLog*(pid: PeerId): string = func shortLog*(pid: PeerId): string =
## Returns compact string representation of ``pid``. ## Returns compact string representation of ``pid``.
var spid = $pid var spid = $pid
if len(spid) <= 10: if len(spid) > 10:
result = spid spid[3] = '*'
else: spid.delete(4, spid.high - 6)
result = newStringOfCap(10)
for i in 0..<2: spid
result.add(spid[i])
result.add("*")
for i in (len(spid) - 6)..spid.high:
result.add(spid[i])
chronicles.formatIt(PeerID): shortLog(it) chronicles.formatIt(PeerID): shortLog(it)
proc toBytes*(pid: PeerID, data: var openarray[byte]): int = func toBytes*(pid: PeerID, data: var openarray[byte]): int =
## Store PeerID ``pid`` to array of bytes ``data``. ## Store PeerID ``pid`` to array of bytes ``data``.
## ##
## Returns number of bytes needed to store ``pid``. ## Returns number of bytes needed to store ``pid``.
@ -56,20 +51,19 @@ proc toBytes*(pid: PeerID, data: var openarray[byte]): int =
if len(data) >= result and result > 0: if len(data) >= result and result > 0:
copyMem(addr data[0], unsafeAddr pid.data[0], result) copyMem(addr data[0], unsafeAddr pid.data[0], result)
proc getBytes*(pid: PeerID): seq[byte] {.inline.} = template getBytes*(pid: PeerID): seq[byte] =
## Return PeerID ``pid`` as array of bytes. ## Return PeerID ``pid`` as array of bytes.
result = pid.data pid.data
proc hex*(pid: PeerID): string {.inline.} = func hex*(pid: PeerID): string =
## Returns hexadecimal string representation of ``pid``. ## Returns hexadecimal string representation of ``pid``.
if len(pid.data) > 0: toHex(pid.data)
result = toHex(pid.data)
proc len*(pid: PeerID): int {.inline.} = template len*(pid: PeerID): int =
## Returns length of ``pid`` binary representation. ## Returns length of ``pid`` binary representation.
result = len(pid.data) len(pid.data)
proc cmp*(a, b: PeerID): int = func cmp*(a, b: PeerID): int =
## Compares two peer ids ``a`` and ``b``. ## Compares two peer ids ``a`` and ``b``.
## Returns: ## Returns:
## ##
@ -84,30 +78,29 @@ proc cmp*(a, b: PeerID): int =
inc(i) inc(i)
result = len(a.data) - len(b.data) result = len(a.data) - len(b.data)
proc `<=`*(a, b: PeerID): bool {.inline.} = template `<=`*(a, b: PeerID): bool =
(cmp(a, b) <= 0) (cmp(a, b) <= 0)
proc `<`*(a, b: PeerID): bool {.inline.} = template `<`*(a, b: PeerID): bool =
(cmp(a, b) < 0) (cmp(a, b) < 0)
proc `>=`*(a, b: PeerID): bool {.inline.} = template `>=`*(a, b: PeerID): bool =
(cmp(a, b) >= 0) (cmp(a, b) >= 0)
proc `>`*(a, b: PeerID): bool {.inline.} = template `>`*(a, b: PeerID): bool =
(cmp(a, b) > 0) (cmp(a, b) > 0)
proc `==`*(a, b: PeerID): bool {.inline.} = template `==`*(a, b: PeerID): bool =
(cmp(a, b) == 0) (cmp(a, b) == 0)
proc hash*(pid: PeerID): Hash {.inline.} = template hash*(pid: PeerID): Hash =
result = hash(pid.data) hash(pid.data)
proc validate*(pid: PeerID): bool = func validate*(pid: PeerID): bool =
## Validate check if ``pid`` is empty or not. ## Validate check if ``pid`` is empty or not.
if len(pid.data) > 0: len(pid.data) > 0 and MultiHash.validate(pid.data)
result = MultiHash.validate(pid.data)
proc hasPublicKey*(pid: PeerID): bool = func hasPublicKey*(pid: PeerID): bool =
## Returns ``true`` if ``pid`` is small enough to hold public key inside. ## Returns ``true`` if ``pid`` is small enough to hold public key inside.
if len(pid.data) > 0: if len(pid.data) > 0:
var mh: MultiHash var mh: MultiHash
@ -115,19 +108,19 @@ proc hasPublicKey*(pid: PeerID): bool =
if mh.mcodec == multiCodec("identity"): if mh.mcodec == multiCodec("identity"):
result = true result = true
proc extractPublicKey*(pid: PeerID, pubkey: var PublicKey): bool = func extractPublicKey*(pid: PeerID, pubkey: var PublicKey): bool =
## Returns ``true`` if public key was successfully decoded from PeerID ## Returns ``true`` if public key was successfully decoded from PeerID
## ``pid``and stored to ``pubkey``. ## ``pid``and stored to ``pubkey``.
## ##
## Returns ``false`` otherwise. ## Returns ``false`` otherwise.
var mh: MultiHash
if len(pid.data) > 0: if len(pid.data) > 0:
var mh: MultiHash
if MultiHash.decode(pid.data, mh).isOk: if MultiHash.decode(pid.data, mh).isOk:
if mh.mcodec == multiCodec("identity"): if mh.mcodec == multiCodec("identity"):
let length = len(mh.data.buffer) let length = len(mh.data.buffer)
result = pubkey.init(mh.data.buffer.toOpenArray(mh.dpos, length - 1)) result = pubkey.init(mh.data.buffer.toOpenArray(mh.dpos, length - 1))
proc init*(pid: var PeerID, data: openarray[byte]): bool = func init*(pid: var PeerID, data: openarray[byte]): bool =
## Initialize peer id from raw binary representation ``data``. ## Initialize peer id from raw binary representation ``data``.
## ##
## Returns ``true`` if peer was successfully initialiazed. ## Returns ``true`` if peer was successfully initialiazed.
@ -136,7 +129,7 @@ proc init*(pid: var PeerID, data: openarray[byte]): bool =
pid = p pid = p
result = true result = true
proc init*(pid: var PeerID, data: string): bool = func init*(pid: var PeerID, data: string): bool =
## Initialize peer id from base58 encoded string representation. ## Initialize peer id from base58 encoded string representation.
## ##
## Returns ``true`` if peer was successfully initialiazed. ## Returns ``true`` if peer was successfully initialiazed.
@ -150,7 +143,7 @@ proc init*(pid: var PeerID, data: string): bool =
pid = opid pid = opid
result = true result = true
proc init*(t: typedesc[PeerID], data: openarray[byte]): Result[PeerID, cstring] {.inline.} = func init*(t: typedesc[PeerID], data: openarray[byte]): Result[PeerID, cstring] =
## Create new peer id from raw binary representation ``data``. ## Create new peer id from raw binary representation ``data``.
var res: PeerID var res: PeerID
if not init(res, data): if not init(res, data):
@ -158,7 +151,7 @@ proc init*(t: typedesc[PeerID], data: openarray[byte]): Result[PeerID, cstring]
else: else:
ok(res) ok(res)
proc init*(t: typedesc[PeerID], data: string): Result[PeerID, cstring] {.inline.} = func init*(t: typedesc[PeerID], data: string): Result[PeerID, cstring] =
## Create new peer id from base58 encoded string representation ``data``. ## Create new peer id from base58 encoded string representation ``data``.
var res: PeerID var res: PeerID
if not init(res, data): if not init(res, data):
@ -166,9 +159,10 @@ proc init*(t: typedesc[PeerID], data: string): Result[PeerID, cstring] {.inline.
else: else:
ok(res) ok(res)
proc init*(t: typedesc[PeerID], pubkey: PublicKey): Result[PeerID, cstring] = func init*(t: typedesc[PeerID], pubkey: PublicKey): Result[PeerID, cstring] =
## Create new peer id from public key ``pubkey``. ## Create new peer id from public key ``pubkey``.
var pubraw = ? pubkey.getBytes().orError("peerid: failed to get bytes from given key") var pubraw = ? pubkey.getBytes().orError(
cstring("peerid: failed to get bytes from given key"))
var mh: MultiHash var mh: MultiHash
if len(pubraw) <= maxInlineKeyLength: if len(pubraw) <= maxInlineKeyLength:
mh = ? MultiHash.digest("identity", pubraw) mh = ? MultiHash.digest("identity", pubraw)
@ -176,11 +170,11 @@ proc init*(t: typedesc[PeerID], pubkey: PublicKey): Result[PeerID, cstring] =
mh = ? MultiHash.digest("sha2-256", pubraw) mh = ? MultiHash.digest("sha2-256", pubraw)
ok(PeerID(data: mh.data.buffer)) ok(PeerID(data: mh.data.buffer))
proc init*(t: typedesc[PeerID], seckey: PrivateKey): Result[PeerID, cstring] {.inline.} = func init*(t: typedesc[PeerID], seckey: PrivateKey): Result[PeerID, cstring] =
## Create new peer id from private key ``seckey``. ## Create new peer id from private key ``seckey``.
PeerID.init(? seckey.getKey().orError("invalid private key")) PeerID.init(? seckey.getKey().orError(cstring("invalid private key")))
proc match*(pid: PeerID, pubkey: PublicKey): bool {.inline.} = func match*(pid: PeerID, pubkey: PublicKey): bool =
## Returns ``true`` if ``pid`` matches public key ``pubkey``. ## Returns ``true`` if ``pid`` matches public key ``pubkey``.
let p = PeerID.init(pubkey) let p = PeerID.init(pubkey)
if p.isErr: if p.isErr:
@ -188,7 +182,7 @@ proc match*(pid: PeerID, pubkey: PublicKey): bool {.inline.} =
else: else:
pid == p.get() pid == p.get()
proc match*(pid: PeerID, seckey: PrivateKey): bool {.inline.} = func match*(pid: PeerID, seckey: PrivateKey): bool =
## Returns ``true`` if ``pid`` matches private key ``seckey``. ## Returns ``true`` if ``pid`` matches private key ``seckey``.
let p = PeerID.init(seckey) let p = PeerID.init(seckey)
if p.isErr: if p.isErr:
@ -198,15 +192,15 @@ proc match*(pid: PeerID, seckey: PrivateKey): bool {.inline.} =
## Serialization/Deserialization helpers ## Serialization/Deserialization helpers
proc write*(vb: var VBuffer, pid: PeerID) {.inline.} = func write*(vb: var VBuffer, pid: PeerID) =
## Write PeerID value ``peerid`` to buffer ``vb``. ## Write PeerID value ``peerid`` to buffer ``vb``.
vb.writeSeq(pid.data) vb.writeSeq(pid.data)
proc initProtoField*(index: int, pid: PeerID): ProtoField {.deprecated.} = func initProtoField*(index: int, pid: PeerID): ProtoField {.deprecated.} =
## Initialize ProtoField with PeerID ``value``. ## Initialize ProtoField with PeerID ``value``.
result = initProtoField(index, pid.data) initProtoField(index, pid.data)
proc getValue*(data: var ProtoBuffer, field: int, value: var PeerID): int {. func getValue*(data: var ProtoBuffer, field: int, value: var PeerID): int {.
deprecated.} = deprecated.} =
## Read ``PeerID`` from ProtoBuf's message and validate it. ## Read ``PeerID`` from ProtoBuf's message and validate it.
var pid: PeerID var pid: PeerID
@ -217,11 +211,11 @@ proc getValue*(data: var ProtoBuffer, field: int, value: var PeerID): int {.
else: else:
value = pid value = pid
proc write*(pb: var ProtoBuffer, field: int, pid: PeerID) = func write*(pb: var ProtoBuffer, field: int, pid: PeerID) =
## Write PeerID value ``peerid`` to object ``pb`` using ProtoBuf's encoding. ## Write PeerID value ``peerid`` to object ``pb`` using ProtoBuf's encoding.
write(pb, field, pid.data) write(pb, field, pid.data)
proc getField*(pb: ProtoBuffer, field: int, func getField*(pb: ProtoBuffer, field: int,
pid: var PeerID): ProtoResult[bool] {.inline.} = pid: var PeerID): ProtoResult[bool] {.inline.} =
## Read ``PeerID`` from ProtoBuf's message and validate it ## Read ``PeerID`` from ProtoBuf's message and validate it
var buffer: seq[byte] var buffer: seq[byte]

View File

@ -20,20 +20,20 @@ type
MCache* = object of RootObj MCache* = object of RootObj
msgs*: Table[MessageID, Message] msgs*: Table[MessageID, Message]
history*: seq[seq[CacheEntry]] history*: seq[seq[CacheEntry]]
historySize*: Natural
windowSize*: Natural windowSize*: Natural
func get*(c: MCache, mid: MessageID): Option[Message] = func get*(c: MCache, mid: MessageID): Option[Message] =
result = none(Message)
if mid in c.msgs: if mid in c.msgs:
result = some(c.msgs[mid]) some(c.msgs[mid])
else:
none(Message)
func contains*(c: MCache, mid: MessageID): bool = func contains*(c: MCache, mid: MessageID): bool =
c.get(mid).isSome c.get(mid).isSome
func put*(c: var MCache, msgId: MessageID, msg: Message) = func put*(c: var MCache, msgId: MessageID, msg: Message) =
if msgId notin c.msgs: if not c.msgs.hasKeyOrPut(msgId, msg):
c.msgs[msgId] = msg # Only add cache entry if the message was not already in the cache
c.history[0].add(CacheEntry(mid: msgId, topicIDs: msg.topicIDs)) c.history[0].add(CacheEntry(mid: msgId, topicIDs: msg.topicIDs))
func window*(c: MCache, topic: string): HashSet[MessageID] = func window*(c: MCache, topic: string): HashSet[MessageID] =
@ -58,6 +58,5 @@ func shift*(c: var MCache) =
func init*(T: type MCache, window, history: Natural): T = func init*(T: type MCache, window, history: Natural): T =
T( T(
history: newSeq[seq[CacheEntry]](history), history: newSeq[seq[CacheEntry]](history),
historySize: history,
windowSize: window windowSize: window
) )

View File

@ -13,7 +13,7 @@ import testmultibase,
testmultihash, testmultihash,
testmultiaddress, testmultiaddress,
testcid, testcid,
testpeer testpeerid
import testtransport, import testtransport,
testmultistream, testmultistream,

View File

@ -220,6 +220,7 @@ suite "Peer testing suite":
$p1 == $p2 $p1 == $p2
$p1 == $p3 $p1 == $p3
$p1 == $p4 $p1 == $p4
len(shortLog(p1)) <= 10
if i in {3, 4, 5}: if i in {3, 4, 5}:
var ekey1, ekey2, ekey3, ekey4: PublicKey var ekey1, ekey2, ekey3, ekey4: PublicKey
check: check: