pp2p-core 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: pp2p_core
3
+ Version: 0.1.0
4
+ Summary: Python ctypes SDK for the PP2P Rust core
5
+ Author: PP2P
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Python SDK
14
+
15
+ This package is a ctypes bridge over the PP2P Rust C ABI.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install pp2p_core
21
+ ```
22
+
23
+ ## Runtime requirements
24
+
25
+ - Python 3.9+
26
+ - Native PP2P core library (`pp2p_core.dll` / `libpp2p_core.so` / `libpp2p_core.dylib`)
27
+
28
+ Build native library first:
29
+
30
+ Windows:
31
+ ```powershell
32
+ .\scripts\build_pp2p_core.ps1
33
+ ```
34
+
35
+ Linux/macOS:
36
+ ```bash
37
+ ./scripts/build_pp2p_core_unix.sh
38
+ ```
39
+
40
+ If the library is not in `dist/pp2p_core/...`, set `PP2P_CORE_LIB` to its absolute path.
41
+
42
+ ## Local dev install
43
+
44
+ ```bash
45
+ pip install -e ./bindings/python
46
+ ```
47
+
48
+ ## Example
49
+
50
+ ```python
51
+ from pp2p_core import Pp2pCore
52
+
53
+ core = Pp2pCore()
54
+ alice = core.generate_identity()
55
+ bob = core.generate_identity()
56
+
57
+ env = core.sign_envelope(
58
+ private_key_b64=alice["private_key_b64"],
59
+ sender_peer_id=alice["peer_id"],
60
+ recipient_peer_id=bob["peer_id"],
61
+ payload={"type": "hello", "text": "hi"},
62
+ nonce="n1",
63
+ )
64
+ core.verify_envelope(env, signer_public_key_b64=alice["public_key_b64"])
65
+ print("ok")
66
+ ```
@@ -0,0 +1,54 @@
1
+ # Python SDK
2
+
3
+ This package is a ctypes bridge over the PP2P Rust C ABI.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install pp2p_core
9
+ ```
10
+
11
+ ## Runtime requirements
12
+
13
+ - Python 3.9+
14
+ - Native PP2P core library (`pp2p_core.dll` / `libpp2p_core.so` / `libpp2p_core.dylib`)
15
+
16
+ Build native library first:
17
+
18
+ Windows:
19
+ ```powershell
20
+ .\scripts\build_pp2p_core.ps1
21
+ ```
22
+
23
+ Linux/macOS:
24
+ ```bash
25
+ ./scripts/build_pp2p_core_unix.sh
26
+ ```
27
+
28
+ If the library is not in `dist/pp2p_core/...`, set `PP2P_CORE_LIB` to its absolute path.
29
+
30
+ ## Local dev install
31
+
32
+ ```bash
33
+ pip install -e ./bindings/python
34
+ ```
35
+
36
+ ## Example
37
+
38
+ ```python
39
+ from pp2p_core import Pp2pCore
40
+
41
+ core = Pp2pCore()
42
+ alice = core.generate_identity()
43
+ bob = core.generate_identity()
44
+
45
+ env = core.sign_envelope(
46
+ private_key_b64=alice["private_key_b64"],
47
+ sender_peer_id=alice["peer_id"],
48
+ recipient_peer_id=bob["peer_id"],
49
+ payload={"type": "hello", "text": "hi"},
50
+ nonce="n1",
51
+ )
52
+ core.verify_envelope(env, signer_public_key_b64=alice["public_key_b64"])
53
+ print("ok")
54
+ ```
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: pp2p_core
3
+ Version: 0.1.0
4
+ Summary: Python ctypes SDK for the PP2P Rust core
5
+ Author: PP2P
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Python SDK
14
+
15
+ This package is a ctypes bridge over the PP2P Rust C ABI.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install pp2p_core
21
+ ```
22
+
23
+ ## Runtime requirements
24
+
25
+ - Python 3.9+
26
+ - Native PP2P core library (`pp2p_core.dll` / `libpp2p_core.so` / `libpp2p_core.dylib`)
27
+
28
+ Build native library first:
29
+
30
+ Windows:
31
+ ```powershell
32
+ .\scripts\build_pp2p_core.ps1
33
+ ```
34
+
35
+ Linux/macOS:
36
+ ```bash
37
+ ./scripts/build_pp2p_core_unix.sh
38
+ ```
39
+
40
+ If the library is not in `dist/pp2p_core/...`, set `PP2P_CORE_LIB` to its absolute path.
41
+
42
+ ## Local dev install
43
+
44
+ ```bash
45
+ pip install -e ./bindings/python
46
+ ```
47
+
48
+ ## Example
49
+
50
+ ```python
51
+ from pp2p_core import Pp2pCore
52
+
53
+ core = Pp2pCore()
54
+ alice = core.generate_identity()
55
+ bob = core.generate_identity()
56
+
57
+ env = core.sign_envelope(
58
+ private_key_b64=alice["private_key_b64"],
59
+ sender_peer_id=alice["peer_id"],
60
+ recipient_peer_id=bob["peer_id"],
61
+ payload={"type": "hello", "text": "hi"},
62
+ nonce="n1",
63
+ )
64
+ core.verify_envelope(env, signer_public_key_b64=alice["public_key_b64"])
65
+ print("ok")
66
+ ```
@@ -0,0 +1,7 @@
1
+ README.md
2
+ pp2p_core.py
3
+ pyproject.toml
4
+ pp2p_core.egg-info/PKG-INFO
5
+ pp2p_core.egg-info/SOURCES.txt
6
+ pp2p_core.egg-info/dependency_links.txt
7
+ pp2p_core.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ pp2p_core
@@ -0,0 +1,131 @@
1
+ """
2
+ Python ctypes bridge for the Rust PP2P core C ABI.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import ctypes
8
+ import json
9
+ import os
10
+ import pathlib
11
+ import time
12
+ from typing import Any
13
+
14
+
15
+ def _default_library_path() -> str:
16
+ env = os.environ.get("PP2P_CORE_LIB")
17
+ if env:
18
+ return env
19
+
20
+ if os.name == "nt":
21
+ rel = pathlib.Path("dist") / "pp2p_core" / "windows-x64" / "pp2p_core.dll"
22
+ elif os.uname().sysname == "Darwin":
23
+ rel = pathlib.Path("dist") / "pp2p_core" / "macos" / "libpp2p_core.dylib"
24
+ else:
25
+ rel = pathlib.Path("dist") / "pp2p_core" / "linux-x64" / "libpp2p_core.so"
26
+
27
+ candidates = [
28
+ pathlib.Path(__file__).resolve().parents[2] / rel,
29
+ pathlib.Path.cwd() / rel,
30
+ ]
31
+ for candidate in candidates:
32
+ if candidate.exists():
33
+ return str(candidate)
34
+
35
+ # Return best-guess path so ctypes error mentions a useful location.
36
+ return str(candidates[0])
37
+
38
+
39
+ class Pp2pCoreError(RuntimeError):
40
+ pass
41
+
42
+
43
+ class Pp2pCore:
44
+ def __init__(self, lib_path: str | None = None) -> None:
45
+ path = lib_path or _default_library_path()
46
+ self._lib = ctypes.CDLL(path)
47
+
48
+ self._lib.pp2p_generate_identity_json.restype = ctypes.c_void_p
49
+ self._lib.pp2p_peer_id_from_public_key_b64.argtypes = [ctypes.c_char_p]
50
+ self._lib.pp2p_peer_id_from_public_key_b64.restype = ctypes.c_void_p
51
+ self._lib.pp2p_sign_envelope_json.argtypes = [
52
+ ctypes.c_char_p,
53
+ ctypes.c_char_p,
54
+ ctypes.c_char_p,
55
+ ctypes.c_char_p,
56
+ ctypes.c_uint64,
57
+ ctypes.c_char_p,
58
+ ]
59
+ self._lib.pp2p_sign_envelope_json.restype = ctypes.c_void_p
60
+ self._lib.pp2p_verify_envelope_json.argtypes = [
61
+ ctypes.c_char_p,
62
+ ctypes.c_char_p,
63
+ ctypes.c_uint64,
64
+ ctypes.c_uint64,
65
+ ]
66
+ self._lib.pp2p_verify_envelope_json.restype = ctypes.c_ubyte
67
+ self._lib.pp2p_last_error_message.restype = ctypes.c_void_p
68
+ self._lib.pp2p_free_string.argtypes = [ctypes.c_void_p]
69
+
70
+ def _take_string(self, ptr: int | None) -> str:
71
+ if not ptr:
72
+ raise Pp2pCoreError(self.last_error())
73
+ try:
74
+ raw = ctypes.cast(ptr, ctypes.c_char_p).value or b""
75
+ return raw.decode("utf-8")
76
+ finally:
77
+ self._lib.pp2p_free_string(ptr)
78
+
79
+ def last_error(self) -> str:
80
+ ptr = self._lib.pp2p_last_error_message()
81
+ if not ptr:
82
+ return "unknown error"
83
+ return self._take_string(ptr)
84
+
85
+ def generate_identity(self) -> dict[str, Any]:
86
+ ptr = self._lib.pp2p_generate_identity_json()
87
+ return json.loads(self._take_string(ptr))
88
+
89
+ def peer_id_from_public_key_b64(self, public_key_b64: str) -> str:
90
+ ptr = self._lib.pp2p_peer_id_from_public_key_b64(public_key_b64.encode("utf-8"))
91
+ return self._take_string(ptr)
92
+
93
+ def sign_envelope(
94
+ self,
95
+ private_key_b64: str,
96
+ sender_peer_id: str,
97
+ recipient_peer_id: str,
98
+ payload: dict[str, Any],
99
+ nonce: str,
100
+ timestamp_ms: int | None = None,
101
+ ) -> dict[str, Any]:
102
+ if timestamp_ms is None:
103
+ timestamp_ms = int(time.time() * 1000)
104
+ ptr = self._lib.pp2p_sign_envelope_json(
105
+ private_key_b64.encode("utf-8"),
106
+ sender_peer_id.encode("utf-8"),
107
+ recipient_peer_id.encode("utf-8"),
108
+ json.dumps(payload, separators=(",", ":")).encode("utf-8"),
109
+ ctypes.c_uint64(timestamp_ms),
110
+ nonce.encode("utf-8"),
111
+ )
112
+ return json.loads(self._take_string(ptr))
113
+
114
+ def verify_envelope(
115
+ self,
116
+ envelope: dict[str, Any],
117
+ signer_public_key_b64: str,
118
+ max_skew_ms: int = 60_000,
119
+ now_ms: int | None = None,
120
+ ) -> bool:
121
+ if now_ms is None:
122
+ now_ms = int(time.time() * 1000)
123
+ ok = self._lib.pp2p_verify_envelope_json(
124
+ json.dumps(envelope, separators=(",", ":")).encode("utf-8"),
125
+ signer_public_key_b64.encode("utf-8"),
126
+ ctypes.c_uint64(now_ms),
127
+ ctypes.c_uint64(max_skew_ms),
128
+ )
129
+ if ok == 1:
130
+ return True
131
+ raise Pp2pCoreError(self.last_error())
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pp2p_core"
7
+ version = "0.1.0"
8
+ description = "Python ctypes SDK for the PP2P Rust core"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ authors = [{ name = "PP2P" }]
12
+ license = "MIT"
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3 :: Only",
16
+ "Operating System :: OS Independent",
17
+ ]
18
+
19
+ [tool.setuptools]
20
+ py-modules = ["pp2p_core"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+