Peer resultification and defect only (#245)

* Peer resultification and defect only

* Fixing some tests

* test fixes

* Rename peer into peerid

* better result error message in identify

* further merge fixes
This commit is contained in:
Giovanni Petrantoni 2020-07-01 15:25:09 +09:00 committed by GitHub
parent c788a6a3c0
commit ec00c7fc50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 103 additions and 83 deletions

View File

@ -18,7 +18,7 @@ import ../libp2p/[switch,
multiaddress,
peerinfo,
crypto/crypto,
peer,
peerid,
protocols/protocol,
muxers/muxer,
muxers/mplex/mplex,

View File

@ -12,7 +12,7 @@ import ../libp2p/[switch,
transports/tcptransport,
multiaddress,
peerinfo,
peer,
peerid,
protocols/protocol,
protocols/secure/secure,
protocols/secure/secio,

View File

@ -12,7 +12,7 @@ import ../libp2p/[switch,
transports/tcptransport,
multiaddress,
peerinfo,
peer,
peerid,
protocols/protocol,
protocols/secure/secure,
protocols/secure/secio,

View File

@ -13,7 +13,7 @@ import ../libp2p/[switch, # manage transports, a single entry
transports/tcptransport, # listen and dial to other peers using client-server protocol
multiaddress, # encode different addressing schemes. For example, /ip4/7.7.7.7/tcp/6543 means it is using IPv4 protocol and TCP
peerinfo, # manage the information of a peer, such as peer ID and public / private key
peer, # Implement how peers interact
peerid, # Implement how peers interact
protocols/protocol, # define the protocol base type
protocols/secure/secure, # define the protocol of secure connection
protocols/secure/secio, # define the protocol of secure input / output, allows encrypted communication that uses public keys to validate signed messages instead of a certificate authority like in TLS

View File

@ -95,7 +95,7 @@ const
SupportedSchemesInt* = {int8(RSA), int8(Ed25519), int8(Secp256k1),
int8(ECDSA)}
template orError(exp: untyped, err: CryptoError): untyped =
template orError*(exp: untyped, err: untyped): untyped =
(exp.mapErr do (_: auto) -> auto: err)
proc random*(t: typedesc[PrivateKey], scheme: PKScheme,

View File

@ -10,11 +10,11 @@
## This module implementes API for `go-libp2p-daemon`.
import os, osproc, strutils, tables, strtabs
import chronos
import ../varint, ../multiaddress, ../multicodec, ../cid, ../peer
import ../varint, ../multiaddress, ../multicodec, ../cid, ../peerid
import ../wire, ../multihash, ../protobuf/minprotobuf
import ../crypto/crypto
export peer, multiaddress, multicodec, multihash, cid, crypto, wire
export peerid, multiaddress, multicodec, multihash, cid, crypto, wire
when not defined(windows):
import posix

View File

@ -14,9 +14,8 @@
import nativesockets
import tables, strutils, stew/shims/net
import chronos
import multicodec, multihash, multibase, transcoder, vbuffer
import multicodec, multihash, multibase, transcoder, vbuffer, peerid
import stew/[base58, base32, endians2, results]
from peer import PeerID
export results
type

View File

@ -8,10 +8,15 @@
## those terms.
## This module implementes API for libp2p peer.
{.push raises: [Defect].}
import hashes
import nimcrypto/utils, stew/base58
import crypto/crypto, multicodec, multihash, vbuffer
import protobuf/minprotobuf
import stew/results
export results
const
maxInlineKeyLength* = 42
@ -143,37 +148,51 @@ proc init*(pid: var PeerID, data: string): bool =
pid = opid
result = true
proc init*(t: typedesc[PeerID], data: openarray[byte]): PeerID {.inline.} =
proc init*(t: typedesc[PeerID], data: openarray[byte]): Result[PeerID, cstring] {.inline.} =
## Create new peer id from raw binary representation ``data``.
if not init(result, data):
raise newException(PeerIDError, "Incorrect PeerID binary form")
var res: PeerID
if not init(res, data):
err("peerid: incorrect PeerID binary form")
else:
ok(res)
proc init*(t: typedesc[PeerID], data: string): PeerID {.inline.} =
proc init*(t: typedesc[PeerID], data: string): Result[PeerID, cstring] {.inline.} =
## Create new peer id from base58 encoded string representation ``data``.
if not init(result, data):
raise newException(PeerIDError, "Incorrect PeerID string")
var res: PeerID
if not init(res, data):
err("peerid: incorrect PeerID string")
else:
ok(res)
proc init*(t: typedesc[PeerID], pubkey: PublicKey): PeerID =
proc init*(t: typedesc[PeerID], pubkey: PublicKey): Result[PeerID, cstring] =
## Create new peer id from public key ``pubkey``.
var pubraw = pubkey.getBytes().tryGet()
var pubraw = ? pubkey.getBytes().orError("peerid: failed to get bytes from given key")
var mh: MultiHash
if len(pubraw) <= maxInlineKeyLength:
mh = MultiHash.digest("identity", pubraw).tryGet()
mh = ? MultiHash.digest("identity", pubraw)
else:
mh = MultiHash.digest("sha2-256", pubraw).tryGet()
result.data = mh.data.buffer
mh = ? MultiHash.digest("sha2-256", pubraw)
ok(PeerID(data: mh.data.buffer))
proc init*(t: typedesc[PeerID], seckey: PrivateKey): PeerID {.inline.} =
proc init*(t: typedesc[PeerID], seckey: PrivateKey): Result[PeerID, cstring] {.inline.} =
## Create new peer id from private key ``seckey``.
result = PeerID.init(seckey.getKey().tryGet())
PeerID.init(? seckey.getKey().orError("invalid private key"))
proc match*(pid: PeerID, pubkey: PublicKey): bool {.inline.} =
## Returns ``true`` if ``pid`` matches public key ``pubkey``.
result = (pid == PeerID.init(pubkey))
let p = PeerID.init(pubkey)
if p.isErr:
false
else:
pid == p.get()
proc match*(pid: PeerID, seckey: PrivateKey): bool {.inline.} =
## Returns ``true`` if ``pid`` matches private key ``seckey``.
result = (pid == PeerID.init(seckey))
let p = PeerID.init(seckey)
if p.isErr:
false
else:
pid == p.get()
## Serialization/Deserialization helpers

View File

@ -9,7 +9,7 @@
import options, sequtils
import chronos, chronicles
import peer, multiaddress, crypto/crypto
import peerid, multiaddress, crypto/crypto
## A peer can be constructed in one of tree ways:
## 1) A local peer with a private key
@ -65,7 +65,7 @@ proc init*(p: typedesc[PeerInfo],
key: PrivateKey,
addrs: openarray[MultiAddress] = [],
protocols: openarray[string] = []): PeerInfo {.inline.} =
result = PeerInfo(keyType: HasPrivate, peerId: PeerID.init(key),
result = PeerInfo(keyType: HasPrivate, peerId: PeerID.init(key).tryGet(),
privateKey: key)
result.postInit(addrs, protocols)
@ -80,7 +80,7 @@ proc init*(p: typedesc[PeerInfo],
peerId: string,
addrs: openarray[MultiAddress] = [],
protocols: openarray[string] = []): PeerInfo {.inline.} =
result = PeerInfo(keyType: HasPublic, peerId: PeerID.init(peerId))
result = PeerInfo(keyType: HasPublic, peerId: PeerID.init(peerId).tryGet())
result.postInit(addrs, protocols)
proc init*(p: typedesc[PeerInfo],
@ -88,7 +88,7 @@ proc init*(p: typedesc[PeerInfo],
addrs: openarray[MultiAddress] = [],
protocols: openarray[string] = []): PeerInfo {.inline.} =
result = PeerInfo(keyType: HasPublic,
peerId: PeerID.init(key),
peerId: PeerID.init(key).tryGet(),
key: some(key))
result.postInit(addrs, protocols)

View File

@ -12,7 +12,7 @@ import chronos, chronicles
import ../protobuf/minprotobuf,
../peerinfo,
../stream/connection,
../peer,
../peerid,
../crypto/crypto,
../multiaddress,
../protocols/protocol,
@ -142,16 +142,18 @@ proc identify*(p: Identify,
if not isNil(remotePeerInfo) and result.pubKey.isSome:
let peer = PeerID.init(result.pubKey.get())
if peer.isErr:
raise newException(IdentityInvalidMsgError, $peer.error)
else:
# do a string comaprison of the ids,
# because that is the only thing we
# have in most cases
if peer.get() != remotePeerInfo.peerId:
trace "Peer ids don't match",
remote = peer.get().pretty(),
local = remotePeerInfo.id
# do a string comparison of the ids,
# because that is the only thing we
# have in most cases
if peer != remotePeerInfo.peerId:
trace "Peer ids don't match",
remote = peer.pretty(),
local = remotePeerInfo.id
raise newException(IdentityNoMatchError, "Peer ids don't match")
raise newException(IdentityNoMatchError, "Peer ids don't match")
proc push*(p: Identify, conn: Connection) {.async.} =
await conn.write(IdentifyPushCodec)

View File

@ -14,7 +14,7 @@ import pubsub,
timedcache,
rpc/[messages, message],
../../stream/connection,
../../peer,
../../peerid,
../../peerinfo,
../../utility,
../../errors

View File

@ -18,7 +18,7 @@ import pubsub,
../protocol,
../../peerinfo,
../../stream/connection,
../../peer,
../../peerid,
../../errors,
../../utility

View File

@ -13,7 +13,7 @@ import pubsubpeer,
rpc/[message, messages],
../protocol,
../../stream/connection,
../../peer,
../../peerid,
../../peerinfo
import metrics

View File

@ -11,7 +11,7 @@ import options, hashes, strutils, tables, hashes
import chronos, chronicles, nimcrypto/sha2, metrics
import rpc/[messages, message, protobuf],
timedcache,
../../peer,
../../peerid,
../../peerinfo,
../../stream/connection,
../../crypto/crypto,

View File

@ -15,7 +15,7 @@ import metrics
import chronicles
import nimcrypto/sysrand
import messages, protobuf,
../../../peer,
../../../peerid,
../../../peerinfo,
../../../crypto/crypto,
../../../protobuf/minprotobuf

View File

@ -9,7 +9,7 @@
import options, sequtils
import ../../../utility
import ../../../peer
import ../../../peerid
type
SubOpts* = object

View File

@ -10,7 +10,7 @@
import options
import chronicles
import messages,
../../../peer,
../../../peerid,
../../../utility,
../../../protobuf/minprotobuf
@ -186,7 +186,7 @@ proc decodeMessages*(pb: var ProtoBuffer): seq[Message] {.gcsafe.} =
if pb.getBytes(1, fromPeer) < 0:
break
try:
msg.fromPeer = PeerID.init(fromPeer)
msg.fromPeer = PeerID.init(fromPeer).tryGet()
except CatchableError as err:
debug "Invalid fromPeer in message", msg = err.msg
break

View File

@ -12,7 +12,7 @@ import chronicles
import stew/[endians2, byteutils]
import nimcrypto/[utils, sysrand, sha2, hmac]
import ../../stream/lpstream
import ../../peer
import ../../peerid
import ../../peerinfo
import ../../protobuf/minprotobuf
import ../../utility
@ -460,7 +460,7 @@ method handshake*(p: Noise, conn: Connection, initiator: bool): Future[SecureCon
let pid = PeerID.init(remotePubKey)
if not conn.peerInfo.peerId.validate():
raise newException(NoiseHandshakeError, "Failed to validate peerId.")
if pid != conn.peerInfo.peerId:
if pid.isErr or pid.get() != conn.peerInfo.peerId:
var
failedKey: PublicKey
discard extractPublicKey(conn.peerInfo.peerId, failedKey)

View File

@ -13,7 +13,7 @@ import secure,
../../peerinfo,
../../crypto/crypto,
../../crypto/ecnist,
../../peer,
../../peerid,
../../utility
export hmac, sha2, sha, hash, rijndael, bcmode
@ -297,7 +297,7 @@ method handshake*(s: Secio, conn: Connection, initiator: bool = false): Future[S
SecioCiphers,
SecioHashes)
localPeerId = PeerID.init(s.localPublicKey)
localPeerId = PeerID.init(s.localPublicKey).tryGet()
trace "Local proposal", schemes = SecioExchanges,
ciphers = SecioCiphers,
@ -320,7 +320,7 @@ method handshake*(s: Secio, conn: Connection, initiator: bool = false): Future[S
trace "Remote public key incorrect or corrupted", pubkey = remoteBytesPubkey.shortLog
raise (ref SecioError)(msg: "Remote public key incorrect or corrupted")
remotePeerId = PeerID.init(remotePubkey)
remotePeerId = PeerID.init(remotePubkey).tryGet()
# TODO: PeerID check against supplied PeerID
let order = getOrder(remoteBytesPubkey, localNonce, localBytesPubkey,

View File

@ -5,7 +5,7 @@ const
import
options, tables, chronos,
switch, peer, peerinfo, stream/connection, multiaddress,
switch, peerid, peerinfo, stream/connection, multiaddress,
crypto/crypto, transports/[transport, tcptransport],
muxers/[muxer, mplex/mplex, mplex/types],
protocols/[identify, secure/secure],
@ -17,7 +17,7 @@ import
protocols/secure/secio
export
switch, peer, peerinfo, connection, multiaddress, crypto
switch, peerid, peerinfo, connection, multiaddress, crypto
type
SecureProtocol* {.pure.} = enum

View File

@ -31,7 +31,7 @@ import stream/connection,
protocols/pubsub/pubsub,
muxers/muxer,
errors,
peer
peerid
logScope:
topics = "switch"

View File

@ -13,7 +13,7 @@ import unittest, sequtils, options, tables, sets
import chronos, stew/byteutils
import chronicles
import utils, ../../libp2p/[errors,
peer,
peerid,
peerinfo,
stream/connection,
crypto/crypto,

View File

@ -2,7 +2,7 @@
import unittest, options, sets, sequtils
import stew/byteutils
import ../../libp2p/[peer,
import ../../libp2p/[peerid,
crypto/crypto,
protocols/pubsub/mcache,
protocols/pubsub/rpc/message,
@ -11,7 +11,7 @@ import ../../libp2p/[peer,
suite "MCache":
test "put/get":
var mCache = newMCache(3, 5)
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes())
let msgId = defaultMsgIdProvider(msg)
mCache.put(msgId, msg)
@ -21,13 +21,13 @@ suite "MCache":
var mCache = newMCache(3, 5)
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["foo"])
mCache.put(defaultMsgIdProvider(msg), msg)
for i in 0..<5:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["bar"])
mCache.put(defaultMsgIdProvider(msg), msg)
@ -42,7 +42,7 @@ suite "MCache":
var mCache = newMCache(1, 5)
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["foo"])
mCache.put(defaultMsgIdProvider(msg), msg)
@ -51,7 +51,7 @@ suite "MCache":
check mCache.window("foo").len == 0
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["bar"])
mCache.put(defaultMsgIdProvider(msg), msg)
@ -60,7 +60,7 @@ suite "MCache":
check mCache.window("bar").len == 0
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["baz"])
mCache.put(defaultMsgIdProvider(msg), msg)
@ -72,19 +72,19 @@ suite "MCache":
var mCache = newMCache(1, 5)
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["foo"])
mCache.put(defaultMsgIdProvider(msg), msg)
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["bar"])
mCache.put(defaultMsgIdProvider(msg), msg)
for i in 0..<3:
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()),
var msg = Message(fromPeer: PeerID.init(PrivateKey.random(ECDSA).get()).get(),
seqno: "12345".toBytes(),
topicIDs: @["baz"])
mCache.put(defaultMsgIdProvider(msg), msg)

View File

@ -1,6 +1,6 @@
import unittest
import ../../libp2p/[peer, peerinfo,
import ../../libp2p/[peerid, peerinfo,
crypto/crypto,
protocols/pubsub/rpc/message,
protocols/pubsub/rpc/messages]

View File

@ -1,7 +1,7 @@
import unittest
import chronos
import ../libp2p/daemon/daemonapi, ../libp2p/multiaddress, ../libp2p/multicodec,
../libp2p/cid, ../libp2p/multihash, ../libp2p/peer
../libp2p/cid, ../libp2p/multihash, ../libp2p/peerid
when defined(nimHasUsed): {.used.}

View File

@ -3,7 +3,7 @@ import chronos, strutils
import ../libp2p/[protocols/identify,
multiaddress,
peerinfo,
peer,
peerid,
stream/connection,
multistream,
transports/transport,

View File

@ -11,7 +11,7 @@ import ../libp2p/[daemon/daemonapi,
varint,
multihash,
standard_setup,
peer,
peerid,
peerinfo,
switch,
stream/connection,

View File

@ -11,7 +11,7 @@
## https://github.com/libp2p/go-libp2p-peer
import unittest
import nimcrypto/utils, stew/base58
import ../libp2p/crypto/crypto, ../libp2p/peer
import ../libp2p/crypto/crypto, ../libp2p/peerid
when defined(nimHasUsed): {.used.}
@ -103,11 +103,11 @@ suite "Peer testing suite":
for i in 0..<len(PrivateKeys):
var seckey = PrivateKey.init(stripSpaces(PrivateKeys[i])).get()
var pubkey = seckey.getKey().get()
var p1 = PeerID.init(seckey)
var p2 = PeerID.init(pubkey)
var p3 = PeerID.init(PeerIDs[i])
var p1 = PeerID.init(seckey).get()
var p2 = PeerID.init(pubkey).get()
var p3 = PeerID.init(PeerIDs[i]).get()
var b1 = Base58.decode(PeerIDs[i])
var p4 = PeerID.init(b1)
var p4 = PeerID.init(b1).get()
var buf1 = newSeq[byte](len(p1))
var buf2 = newSeq[byte](len(p2))
var buf3 = newSeq[byte](len(p3))

View File

@ -4,13 +4,13 @@ import unittest, options
import chronos
import ../libp2p/crypto/crypto,
../libp2p/peerinfo,
../libp2p/peer
../libp2p/peerid
suite "PeerInfo":
test "Should init with private key":
let seckey = PrivateKey.random(ECDSA).get()
var peerInfo = PeerInfo.init(seckey)
var peerId = PeerID.init(seckey)
var peerId = PeerID.init(seckey).get()
check peerId == peerInfo.peerId
check seckey == peerInfo.privateKey
@ -19,15 +19,15 @@ suite "PeerInfo":
test "Should init with public key":
let seckey = PrivateKey.random(ECDSA).get()
var peerInfo = PeerInfo.init(seckey.getKey().get())
var peerId = PeerID.init(seckey.getKey().get())
var peerId = PeerID.init(seckey.getKey().get()).get()
check peerId == peerInfo.peerId
check seckey.getKey.get() == peerInfo.publicKey.get()
test "Should init from PeerId with public key":
let seckey = PrivateKey.random(Ed25519).get()
var peerInfo = PeerInfo.init(PeerID.init(seckey.getKey.get()))
var peerId = PeerID.init(seckey.getKey.get())
var peerInfo = PeerInfo.init(PeerID.init(seckey.getKey.get()).get())
var peerId = PeerID.init(seckey.getKey.get()).get()
check peerId == peerInfo.peerId
check seckey.getKey.get() == peerInfo.publicKey.get()
@ -36,7 +36,7 @@ suite "PeerInfo":
var peerInfo = PeerInfo.init("QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N")
check:
PeerID.init("QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N") == peerInfo.peerId
PeerID.init("QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N").get() == peerInfo.peerId
# TODO: CIDv1 handling is missing from PeerID
# https://github.com/status-im/nim-libp2p/issues/53
@ -47,16 +47,16 @@ suite "PeerInfo":
# PeerID.init("bafzbeie5745rpv2m6tjyuugywy4d5ewrqgqqhfnf445he3omzpjbx5xqxe") == peerInfo.peerId
test "Should return none if pubkey is missing from id":
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(ECDSA).get()))
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(ECDSA).get()).get())
check peerInfo.publicKey.isNone
test "Should return some if pubkey is present in id":
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519).get()))
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519).get()).get())
check peerInfo.publicKey.isSome
test "join() and isClosed() test":
proc testJoin(): Future[bool] {.async, gcsafe.} =
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519).get()))
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519).get()).get())
check peerInfo.isClosed() == false
var joinFut = peerInfo.join()
check joinFut.finished() == false