From a96718cf9e8969e924ff40eb035502aeecc9f7d3 Mon Sep 17 00:00:00 2001 From: cheatfate Date: Tue, 5 Mar 2019 14:09:26 +0200 Subject: [PATCH] Add PeerID support to multiaddress. Change some PeerID api. Some fixes to chat. --- examples/chat.nim | 30 +++++++-------- libp2p/multiaddress.nim | 13 +++++-- libp2p/peer.nim | 82 +++++++++++++++++++++++++++++------------ 3 files changed, 83 insertions(+), 42 deletions(-) diff --git a/examples/chat.nim b/examples/chat.nim index 4eaba4d64..045b6ef53 100644 --- a/examples/chat.nim +++ b/examples/chat.nim @@ -1,5 +1,5 @@ -import asyncdispatch2, nimcrypto, strutils -import ../libp2p/daemon/daemonapi, ../libp2p/[base58, multiaddress] +import chronos, nimcrypto, strutils +import ../libp2p/daemon/daemonapi const ConsoleAddress = "/tmp/console-chat.sock" @@ -39,10 +39,10 @@ proc serveThread(server: StreamServer, if line.startsWith("/connect"): var parts = line.split(" ") if len(parts) == 2: - var peerId = Base58.decode(parts[1]) - var address = MultiAddress.init(P_P2PCIRCUIT) - address &= MultiAddress.init(P_P2P, peerId) - echo "= Searching for peer ", parts[1] + var peerId = PeerID.init(parts[1]) + var address = MultiAddress.init(multiCodec("p2p-circuit")) + address &= MultiAddress.init(multiCodec("p2p"), peerId) + echo "= Searching for peer ", peerId.pretty() var id = await udata.api.dhtFindPeer(peerId) echo "= Peer " & parts[1] & " found at addresses:" for item in id.addresses: @@ -57,8 +57,8 @@ proc serveThread(server: StreamServer, elif line.startsWith("/search"): var parts = line.split(" ") if len(parts) == 2: - var peerId = Base58.decode(parts[1]) - echo "= Searching for peer ", parts[1] + var peerId = PeerID.init(parts[1]) + echo "= Searching for peer ", peerId.pretty() var id = await udata.api.dhtFindPeer(peerId) echo "= Peer " & parts[1] & " found at addresses:" for item in id.addresses: @@ -66,12 +66,12 @@ proc serveThread(server: StreamServer, elif line.startsWith("/consearch"): var parts = line.split(" ") if len(parts) == 2: - var peerId = Base58.decode(parts[1]) + var peerId = PeerID.init(parts[1]) echo "= Searching for peers connected to peer ", parts[1] var peers = await udata.api.dhtFindPeersConnectedToPeer(peerId) echo "= Found ", len(peers), " connected to peer ", parts[1] for item in peers: - var peer = Base58.encode(item.peer) + var peer = item.peer var addresses = newSeq[string]() var relay = false for a in item.addresses: @@ -80,9 +80,9 @@ proc serveThread(server: StreamServer, relay = true break if relay: - echo peer, " * ", " [", addresses.join(", "), "]" + echo peer.pretty(), " * ", " [", addresses.join(", "), "]" else: - echo peer, " [", addresses.join(", "), "]" + echo peer.pretty(), " [", addresses.join(", "), "]" elif line.startsWith("/exit"): quit(0) else: @@ -112,7 +112,7 @@ proc main() {.async.} = var id = await data.api.identity() proc streamHandler(api: DaemonAPI, stream: P2PStream) {.async.} = - echo "= Peer ", Base58.encode(stream.peer), " joined chat" + echo "= Peer ", stream.peer.pretty(), " joined chat" data.remotes.add(stream.transp) while true: var line = await stream.transp.readLine() @@ -121,8 +121,8 @@ proc main() {.async.} = echo ">> ", line await data.api.addHandler(ServerProtocols, streamHandler) - echo "= Your PeerID is ", Base58.encode(id.peer) - + echo "= Your PeerID is ", id.peer.pretty() + when isMainModule: waitFor(main()) while true: diff --git a/libp2p/multiaddress.nim b/libp2p/multiaddress.nim index 5e952ebdd..ad2d66e8d 100644 --- a/libp2p/multiaddress.nim +++ b/libp2p/multiaddress.nim @@ -10,6 +10,7 @@ ## This module implements MultiAddress. import tables, strutils, net import multicodec, multihash, multibase, transcoder, base58, base32, vbuffer +import peer {.deadCodeElim:on.} @@ -562,7 +563,7 @@ proc validate*(ma: MultiAddress): bool = discard result = true -proc init*(mtype: typedesc[MultiAddress], protocol: int, +proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec, value: openarray[byte]): MultiAddress = ## Initialize MultiAddress object from protocol id ``protocol`` and array ## of bytes ``value``. @@ -582,7 +583,13 @@ proc init*(mtype: typedesc[MultiAddress], protocol: int, result.data.writeSeq(data) result.data.finish() -proc init*(mtype: typedesc[MultiAddress], protocol: int): MultiAddress = +proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec, + value: PeerID): MultiAddress {.inline.} = + ## Initialize MultiAddress object from protocol id ``protocol`` and peer id + ## ``value``. + init(mtype, protocol, cast[seq[byte]](value)) + +proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec): MultiAddress = ## Initialize MultiAddress object from protocol id ``protocol``. let proto = CodeAddresses.getOrDefault(protocol) if proto.kind == None: @@ -590,7 +597,7 @@ proc init*(mtype: typedesc[MultiAddress], protocol: int): MultiAddress = result.data = initVBuffer() if proto.kind != Marker: raise newException(MultiAddressError, "Protocol missing value") - result.data.writeVarint(cast[uint64](proto.code)) + result.data.writeVarint(cast[uint64](proto.mcodec)) result.data.finish() proc getProtocol(name: string): MAProtocol {.inline.} = diff --git a/libp2p/peer.nim b/libp2p/peer.nim index 4edace19c..b8097af7d 100644 --- a/libp2p/peer.nim +++ b/libp2p/peer.nim @@ -19,6 +19,8 @@ const type PeerID* = distinct seq[byte] + PeerIDError* = object of Exception + proc pretty*(peerid: PeerID): string {.inline.} = ## Return base58 encoded ``peerid`` representation. Base58.encode(cast[seq[byte]](peerid)) @@ -37,22 +39,7 @@ proc getBytes*(peerid: PeerID): seq[byte] {.inline.} = var p = cast[seq[byte]](peerid) result = @p -proc fromKey*(pubkey: PublicKey): PeerID = - ## Returns the PeerID corresponding to public key ``pubkey``. - var pubraw = pubkey.getBytes() - var mh: MultiHash - var codec: MultiCodec - if len(pubraw) <= maxInlineKeyLength: - mh = MultiHash.digest("identity", pubraw) - else: - mh = MultiHash.digest("sha2-256", pubraw) - result = cast[PeerID](mh.data.buffer) - -proc fromKey*(seckey: PrivateKey): PeerID {.inline.} = - ## Returns the PeerID corresponding to private key ``seckey``. - result = fromKey(seckey.getKey()) - -proc hex*(peerid: PeerID): string = +proc hex*(peerid: PeerID): string {.inline.} = ## Returns hexadecimal string representation of ``peerid``. var p = cast[seq[byte]](peerid) if len(p) > 0: @@ -124,14 +111,6 @@ proc extractPublicKey*(peerid: PeerID, pubkey: var PublicKey): bool = let length = len(mh.data.buffer) result = pubkey.init(mh.data.buffer.toOpenArray(mh.dpos, length - 1)) -proc match*(peerid: PeerID, pubkey: PublicKey): bool {.inline.} = - ## Returns ``true`` if ``peerid`` matches public key ``pubkey``. - result = (peerid == pubkey.fromKey()) - -proc match*(peerid: PeerID, seckey: PrivateKey): bool {.inline.} = - ## Returns ``true`` if ``peerid`` matches private key ``seckey``. - result = (peerid == seckey.fromKey()) - proc `$`*(peerid: PeerID): string = ## Returns compact string representation of ``peerid``. var pid = peerid.pretty() @@ -144,6 +123,61 @@ proc `$`*(peerid: PeerID): string = for i in (len(pid) - 6)..(len(pid) - 1): result.add(pid[i]) +proc init*(pid: var PeerID, data: openarray[byte]): bool = + ## Initialize peer id from raw binary representation ``data``. + ## + ## Returns ``true`` if peer was successfully initialiazed. + var p = cast[PeerID](@data) + if p.validate(): + pid = p + +proc init*(pid: var PeerID, data: string): bool = + ## Initialize peer id from base58 encoded string representation. + ## + ## Returns ``true`` if peer was successfully initialiazed. + var p = newSeq[byte](len(data) + 4) + var length = 0 + if Base58.decode(data, p, length) == Base58Status.Success: + p.setLen(length) + var opid = cast[PeerID](p) + if opid.validate(): + pid = opid + +proc init*(t: typedesc[PeerID], data: openarray[byte]): PeerID {.inline.} = + ## Create new peer id from raw binary representation ``data``. + if not init(result, data): + raise newException(PeerIDError, "Incorrect PeerID binary form") + +proc init*(t: typedesc[PeerID], data: string): PeerID {.inline.} = + ## Create new peer id from base58 encoded string representation ``data``. + if not init(result, data): + raise newException(PeerIDError, "Incorrect PeerID string") + +proc init*(t: typedesc[PeerID], pubkey: PublicKey): PeerID = + ## Create new peer id from public key ``pubkey``. + var pubraw = pubkey.getBytes() + var mh: MultiHash + var codec: MultiCodec + if len(pubraw) <= maxInlineKeyLength: + mh = MultiHash.digest("identity", pubraw) + else: + mh = MultiHash.digest("sha2-256", pubraw) + result = cast[PeerID](mh.data.buffer) + +proc init*(t: typedesc[PeerID], seckey: PrivateKey): PeerID {.inline.} = + ## Create new peer id from private key ``seckey``. + result = PeerID.init(seckey.getKey()) + +proc match*(peerid: PeerID, pubkey: PublicKey): bool {.inline.} = + ## Returns ``true`` if ``peerid`` matches public key ``pubkey``. + result = (peerid == PeerID.init(pubkey)) + +proc match*(peerid: PeerID, seckey: PrivateKey): bool {.inline.} = + ## Returns ``true`` if ``peerid`` matches private key ``seckey``. + result = (peerid == PeerID.init(seckey)) + +## Serialization/Deserialization helpers + proc write*(vb: var VBuffer, peerid: PeerID) {.inline.} = ## Write PeerID value ``peerid`` to buffer ``vb``. var p = cast[seq[byte]](peerid)