Skip to content

Commit 9c793d3

Browse files
committed
feat: peer id class that parallels rust-libp2p impl
1 parent 84d970d commit 9c793d3

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

binding/python/py/synlink/peer_id.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import hashlib
2+
from functools import cached_property
3+
from typing import Union
4+
5+
import base58
6+
import multihash
7+
from synlink.crypto.typing import PublicKey
8+
from synlink.utils import _check_minimum_version
9+
10+
if _check_minimum_version(3, 11):
11+
from typing import Self
12+
else:
13+
from typing_extensions import Self
14+
15+
16+
class PeerId(object):
17+
def __init__(self, data: Union[bytes, bytearray]):
18+
if isinstance(data, (bytearray,)):
19+
self._id = bytes(data)
20+
elif isinstance(data, (bytes,)):
21+
self._id = data
22+
else:
23+
raise TypeError("only supported types; bytes, and bytearray(s).")
24+
25+
@cached_property
26+
def xor_id(self) -> int:
27+
return int(sha256_digest(self._id).hex(), 16)
28+
29+
@cached_property
30+
def base58(self) -> str:
31+
return base58.b58encode(self._id).decode()
32+
33+
def to_base58(self) -> str:
34+
return self.base58
35+
36+
@classmethod
37+
def from_base58(cls, b58_encoded_peer_id_str: str) -> Self:
38+
peer_id_bytes = base58.b58decode(b58_encoded_peer_id_str)
39+
pid = cls(peer_id_bytes)
40+
return pid
41+
42+
@classmethod
43+
def from_bytes(cls, data: bytes):
44+
return cls(data)
45+
46+
def to_bytes(self) -> bytes:
47+
return self._id
48+
49+
@classmethod
50+
def from_pubkey(cls, key: PublicKey) -> Self:
51+
serialized_key = key.to_bytes()
52+
algo = multihash.Func.sha2_256
53+
mh_digest = multihash.digest(serialized_key, algo)
54+
return cls(mh_digest.encode())
55+
56+
def __bytes__(self) -> bytes:
57+
return self.to_bytes()
58+
59+
def __hash__(self):
60+
return hash(self._id)
61+
62+
def __repr__(self):
63+
return f"<synlink.swarm.peer_id.PeerID {self.to_base58()}>"
64+
65+
def __str__(self):
66+
return self.to_base58()
67+
68+
def __eq__(self, other: object) -> bool:
69+
if isinstance(other, str):
70+
return self.to_base58() == other
71+
elif isinstance(other, bytes):
72+
return self._id == other
73+
elif isinstance(other, PeerId):
74+
return self._id == other._id
75+
else:
76+
raise ValueError("Unsupported type for PeerID comparison.")
77+
78+
79+
def sha256_digest(data: Union[str, bytes]) -> bytes:
80+
if isinstance(data, str):
81+
data = data.encode("utf8")
82+
return hashlib.sha256(data).digest()

0 commit comments

Comments
 (0)