Fix examples.

Add peer.nim.
Switch daemonapi to use PeerID from peer.nim.
This commit is contained in:
cheatfate 2019-03-04 20:22:38 +02:00
parent e6c424618d
commit 1e6c8b2171
No known key found for this signature in database
GPG Key ID: 46ADD633A7201F95
4 changed files with 198 additions and 36 deletions

View File

@ -1,4 +1,4 @@
import asyncdispatch2, nimcrypto, strutils
import chronos, nimcrypto, strutils
import ../libp2p/daemon/daemonapi, ../libp2p/[base58, multicodec, multiaddress]
import hexdump

View File

@ -1,4 +1,4 @@
import asyncdispatch2, nimcrypto, strutils, os
import chronos, nimcrypto, strutils, os
import ../libp2p/daemon/daemonapi, ../libp2p/[base58, multiaddress]
proc main(bn: string) {.async.} =

View File

@ -10,7 +10,7 @@
## This module implementes API for `go-libp2p-daemon`.
import os, osproc, strutils, tables, streams, strtabs
import chronos
import ../varint, ../multiaddress, ../multicodec, ../base58, ../cid
import ../varint, ../multiaddress, ../multicodec, ../base58, ../cid, ../peer
import ../wire, ../protobuf/minprotobuf
when not defined(windows):
@ -76,7 +76,7 @@ type
VALUE = 1,
END = 2
PeerID* = seq[byte]
# PeerID* = seq[byte]
MultiProtocol* = string
LibP2PPublicKey* = seq[byte]
DHTValue* = seq[byte]
@ -745,8 +745,7 @@ proc transactMessage(transp: StreamTransport,
proc getPeerInfo(pb: var ProtoBuffer): PeerInfo =
## Get PeerInfo object from ``pb``.
result.addresses = newSeq[MultiAddress]()
result.peer = newSeq[byte]()
if pb.getBytes(1, result.peer) == -1:
if pb.getValue(1, result.peer) == -1:
raise newException(DaemonLocalError, "Missing required field `peer`!")
var address = newSeq[byte]()
while pb.getBytes(2, address) != -1:
@ -803,10 +802,10 @@ proc openStream*(api: DaemonAPI, peer: PeerID,
pb.withMessage() do:
var res = pb.enterSubmessage()
if res == cast[int](ResponseType.STREAMINFO):
stream.peer = newSeq[byte]()
# stream.peer = newSeq[byte]()
var raddress = newSeq[byte]()
stream.protocol = ""
if pb.getLengthValue(1, stream.peer) == -1:
if pb.getValue(1, stream.peer) == -1:
raise newException(DaemonLocalError, "Missing `peer` field!")
if pb.getLengthValue(2, raddress) == -1:
raise newException(DaemonLocalError, "Missing `address` field!")
@ -825,10 +824,9 @@ proc streamHandler(server: StreamServer, transp: StreamTransport) {.async.} =
var message = await transp.recvMessage()
var pb = initProtoBuffer(message)
var stream = new P2PStream
stream.peer = newSeq[byte]()
var raddress = newSeq[byte]()
stream.protocol = ""
if pb.getLengthValue(1, stream.peer) == -1:
if pb.getValue(1, stream.peer) == -1:
raise newException(DaemonLocalError, "Missing `peer` field!")
if pb.getLengthValue(2, raddress) == -1:
raise newException(DaemonLocalError, "Missing `address` field!")
@ -929,6 +927,10 @@ proc dhtGetSingleValue(pb: var ProtoBuffer): seq[byte] =
if pb.getLengthValue(3, result) == -1:
raise newException(DaemonLocalError, "Missing field `value`!")
proc dhtGetSinglePeerID(pb: var ProtoBuffer): PeerID =
if pb.getValue(3, result) == -1:
raise newException(DaemonLocalError, "Missing field `value`!")
proc enterDhtMessage(pb: var ProtoBuffer, rt: DHTResponseType) {.inline.} =
var dtype: uint
var res = pb.enterSubmessage()
@ -1074,7 +1076,7 @@ proc dhtGetClosestPeers*(api: DaemonAPI, key: string,
var cpb = initProtoBuffer(message)
if cpb.getDhtMessageType() == DHTResponseType.END:
break
list.add(cpb.dhtGetSingleValue())
list.add(cpb.dhtGetSinglePeerID())
result = list
finally:
await api.closeConnection(transp)
@ -1152,12 +1154,11 @@ proc pubsubListPeers*(api: DaemonAPI,
try:
var pb = await transp.transactMessage(requestPSListPeers(topic))
withMessage(pb) do:
var peer: PeerID
pb.enterPsMessage()
var peers = newSeq[PeerID]()
var peer = newSeq[byte]()
while pb.getBytes(2, peer) != -1:
while pb.getValue(2, peer) != -1:
peers.add(peer)
peer.setLen(0)
result = peers
finally:
await api.closeConnection(transp)
@ -1174,28 +1175,25 @@ proc pubsubPublish*(api: DaemonAPI, topic: string,
await api.closeConnection(transp)
proc getPubsubMessage*(pb: var ProtoBuffer): PubSubMessage =
result.data = newSeq[byte]()
result.seqno = newSeq[byte]()
result.signature = newSeq[byte]()
result.key = newSeq[byte]()
discard pb.getValue(1, result.peer)
discard pb.getBytes(2, result.data)
discard pb.getBytes(3, result.seqno)
var item = newSeq[byte]()
for field in 1..6:
while true:
if pb.getBytes(field, item) == -1:
break
if field == 1:
result.peer = item
elif field == 2:
result.data = item
elif field == 3:
result.seqno = item
elif field == 4:
var copyitem = item
var stritem = cast[string](copyitem)
if len(result.topics) == 0:
result.topics = newSeq[string]()
result.topics.add(stritem)
elif field == 5:
result.signature = item
elif field == 6:
result.key = item
item.setLen(0)
while true:
if pb.getBytes(4, item) == -1:
break
var copyitem = item
var stritem = cast[string](copyitem)
if len(result.topics) == 0:
result.topics = newSeq[string]()
result.topics.add(stritem)
item.setLen(0)
discard pb.getBytes(5, result.signature)
discard pb.getBytes(6, result.key)
proc pubsubLoop(api: DaemonAPI, ticket: PubsubTicket) {.async.} =
while true:
@ -1232,7 +1230,7 @@ proc `$`*(pinfo: PeerInfo): string =
## Get string representation of ``PeerInfo`` object.
result = newStringOfCap(128)
result.add("{PeerID: '")
result.add(Base58.encode(pinfo.peer))
result.add($pinfo.peer.pretty())
result.add("' Addresses: [")
let length = len(pinfo.addresses)
for i in 0..<length:

164
libp2p/peer.nim Normal file
View File

@ -0,0 +1,164 @@
## Nim-LibP2P
## Copyright (c) 2018 Status Research & Development GmbH
## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option.
## This file may not be copied, modified, or distributed except according to
## those terms.
## This module implementes API for libp2p peer.
import hashes
import nimcrypto/utils
import crypto/crypto, multicodec, multihash, base58, vbuffer
import protobuf/minprotobuf
const
maxInlineKeyLength* = 42
type
PeerID* = distinct seq[byte]
proc pretty*(peerid: PeerID): string {.inline.} =
## Return base58 encoded ``peerid`` representation.
Base58.encode(cast[seq[byte]](peerid))
proc toBytes*(peerid: PeerID, data: var openarray[byte]): int =
## Store PeerID ``peerid`` to array of bytes ``data``.
##
## Returns number of bytes needed to store ``peerid``.
var p = cast[seq[byte]](peerid)
result = len(p)
if len(data) >= result and result > 0:
copyMem(addr data[0], addr p[0], result)
proc getBytes*(peerid: PeerID): seq[byte] {.inline.} =
## Return PeerID as array of bytes.
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 =
## Returns hexadecimal string representation of ``peerid``.
var p = cast[seq[byte]](peerid)
if len(p) > 0:
result = toHex(p)
proc len*(a: PeerID): int {.borrow.}
proc cmp*(a, b: PeerID): int =
## Compares two peer ids ``a`` and ``b``.
## Returns:
##
## | 0 iff a == b
## | < 0 iff a < b
## | > 0 iff a > b
var ab = cast[seq[byte]](a)
var bb = cast[seq[byte]](b)
var i = 0
var m = min(len(ab), len(bb))
while i < m:
result = ord(ab[i]) - ord(bb[i])
if result != 0: return
inc(i)
result = len(ab) - len(bb)
proc `<=`*(a, b: PeerID): bool {.inline.} =
(cmp(a, b) <= 0)
proc `<`*(a, b: PeerID): bool {.inline.} =
(cmp(a, b) < 0)
proc `>=`*(a, b: PeerID): bool {.inline.} =
(cmp(a, b) >= 0)
proc `>`*(a, b: PeerID): bool {.inline.} =
(cmp(a, b) > 0)
proc `==`*(a, b: PeerID): bool {.inline.} =
(cmp(a, b) == 0)
proc hash*(peerid: PeerID): Hash {.inline.} =
var p = cast[seq[byte]](peerid)
result = hash(p)
proc validate*(peerid: PeerID): bool =
## Validate check if ``peerid`` is empty or not.
var p = cast[seq[byte]](peerid)
if len(p) > 0:
result = MultiHash.validate(p)
proc hasPublicKey*(peerid: PeerID): bool =
## Returns ``true`` if ``peerid`` is small enough to hold public key inside.
var mh: MultiHash
var p = cast[seq[byte]](peerid)
if len(p) > 0:
if MultiHash.decode(p, mh) > 0:
if mh.mcodec == multiCodec("identity"):
result = true
proc extractPublicKey*(peerid: PeerID, pubkey: var PublicKey): bool =
## Returns ``true`` if public key was successfully decoded and stored
## in ``pubkey``.
##
## Returns ``false`` otherwise
var mh: MultiHash
var p = cast[seq[byte]](peerid)
if len(p) > 0:
if MultiHash.decode(p, mh) > 0:
if mh.mcodec == multiCodec("identity"):
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()
if len(pid) <= 10:
result = pid
else:
for i in 0..<2:
result.add(pid[i])
result.add("*")
for i in (len(pid) - 6)..(len(pid) - 1):
result.add(pid[i])
proc write*(vb: var VBuffer, peerid: PeerID) {.inline.} =
## Write PeerID value ``peerid`` to buffer ``vb``.
var p = cast[seq[byte]](peerid)
vb.writeSeq(p)
proc initProtoField*(index: int, peerid: PeerID): ProtoField =
## Initialize ProtoField with PeerID ``value``.
var p = cast[seq[byte]](peerid)
result = initProtoField(index, p)
proc getValue*(data: var ProtoBuffer, field: int, value: var PeerID): int =
## Read ``PeerID`` from ProtoBuf's message and validate it.
var buffer: seq[byte]
result = getLengthValue(data, field, buffer)
if result > 0:
value = cast[PeerID](buffer)
if not value.validate():
result = -1