astreum 0.2.41__py3-none-any.whl → 0.2.61__py3-none-any.whl
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.
- astreum/_communication/message.py +1 -0
- astreum/_communication/peer.py +23 -11
- astreum/_communication/route.py +40 -3
- astreum/_communication/setup.py +72 -4
- astreum/_consensus/account.py +62 -137
- astreum/_consensus/accounts.py +7 -36
- astreum/_consensus/block.py +311 -328
- astreum/_consensus/genesis.py +15 -84
- astreum/_consensus/receipt.py +67 -108
- astreum/_consensus/setup.py +50 -3
- astreum/_consensus/transaction.py +141 -118
- astreum/_consensus/workers/validation.py +5 -2
- astreum/_consensus/workers/verify.py +1 -1
- astreum/_lispeum/expression.py +190 -37
- astreum/_lispeum/high_evaluation.py +232 -173
- astreum/_lispeum/low_evaluation.py +21 -21
- astreum/_lispeum/parser.py +26 -31
- astreum/_node.py +154 -14
- astreum/_storage/__init__.py +7 -5
- astreum/_storage/atom.py +88 -96
- astreum/_storage/patricia.py +51 -16
- astreum/_storage/setup.py +35 -0
- astreum/models/block.py +20 -20
- astreum/utils/bytes.py +24 -0
- astreum/utils/integer.py +25 -0
- astreum/utils/logging.py +219 -0
- {astreum-0.2.41.dist-info → astreum-0.2.61.dist-info}/METADATA +14 -1
- astreum-0.2.61.dist-info/RECORD +57 -0
- astreum-0.2.41.dist-info/RECORD +0 -53
- {astreum-0.2.41.dist-info → astreum-0.2.61.dist-info}/WHEEL +0 -0
- {astreum-0.2.41.dist-info → astreum-0.2.61.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.41.dist-info → astreum-0.2.61.dist-info}/top_level.txt +0 -0
astreum/utils/bytes.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def hex_to_bytes(value: str, *, expected_length: Optional[int] = None) -> bytes:
|
|
5
|
+
"""Convert a 0x-prefixed hex string into raw bytes."""
|
|
6
|
+
if not isinstance(value, str):
|
|
7
|
+
raise TypeError("hex value must be provided as a string")
|
|
8
|
+
|
|
9
|
+
if not value.startswith(("0x", "0X")):
|
|
10
|
+
raise ValueError("hex value must start with '0x'")
|
|
11
|
+
|
|
12
|
+
hex_digits = value[2:]
|
|
13
|
+
if len(hex_digits) % 2:
|
|
14
|
+
raise ValueError("hex value must have an even number of digits")
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
result = bytes.fromhex(hex_digits)
|
|
18
|
+
except ValueError as exc:
|
|
19
|
+
raise ValueError("hex value contains non-hexadecimal characters") from exc
|
|
20
|
+
|
|
21
|
+
if expected_length is not None and len(result) != expected_length:
|
|
22
|
+
raise ValueError(f"hex value must decode to exactly {expected_length} bytes")
|
|
23
|
+
|
|
24
|
+
return result
|
astreum/utils/integer.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional, Union
|
|
4
|
+
|
|
5
|
+
ByteLike = Union[bytes, bytearray, memoryview]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def int_to_bytes(value: Optional[int]) -> bytes:
|
|
9
|
+
"""Convert an integer to a little-endian byte string with minimal length."""
|
|
10
|
+
if value is None:
|
|
11
|
+
return b""
|
|
12
|
+
value = int(value)
|
|
13
|
+
if value == 0:
|
|
14
|
+
return b"\x00"
|
|
15
|
+
length = (value.bit_length() + 7) // 8
|
|
16
|
+
return value.to_bytes(length, "little", signed=False)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def bytes_to_int(data: Optional[ByteLike]) -> int:
|
|
20
|
+
"""Convert a little-endian byte string to an integer."""
|
|
21
|
+
if not data:
|
|
22
|
+
return 0
|
|
23
|
+
if isinstance(data, memoryview):
|
|
24
|
+
data = data.tobytes()
|
|
25
|
+
return int.from_bytes(bytes(data), "little", signed=False)
|
astreum/utils/logging.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import atexit
|
|
4
|
+
import inspect
|
|
5
|
+
import gzip
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
import logging.handlers
|
|
9
|
+
import os
|
|
10
|
+
import pathlib
|
|
11
|
+
import platform
|
|
12
|
+
import queue
|
|
13
|
+
import shutil
|
|
14
|
+
from datetime import datetime, timezone
|
|
15
|
+
from typing import Any, Dict, Optional
|
|
16
|
+
|
|
17
|
+
from blake3 import blake3
|
|
18
|
+
|
|
19
|
+
# Fixed identity for all loggers in this library
|
|
20
|
+
_ORG_NAME = "Astreum"
|
|
21
|
+
_PRODUCT_NAME = "lib-py"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _safe_path(path_str: str) -> Optional[pathlib.Path]:
|
|
25
|
+
try:
|
|
26
|
+
return pathlib.Path(path_str).resolve()
|
|
27
|
+
except Exception:
|
|
28
|
+
try:
|
|
29
|
+
return pathlib.Path(path_str).absolute()
|
|
30
|
+
except Exception:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _hash_path(path: pathlib.Path) -> str:
|
|
35
|
+
try:
|
|
36
|
+
data = str(path).encode("utf-8", errors="ignore")
|
|
37
|
+
except Exception:
|
|
38
|
+
data = repr(path).encode("utf-8", errors="ignore")
|
|
39
|
+
return blake3(data).hexdigest()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _find_caller_path() -> pathlib.Path:
|
|
43
|
+
stack = inspect.stack()
|
|
44
|
+
candidates: list[pathlib.Path] = []
|
|
45
|
+
for frame_info in stack[2:]:
|
|
46
|
+
filename = frame_info.filename
|
|
47
|
+
if not filename:
|
|
48
|
+
continue
|
|
49
|
+
path = _safe_path(filename)
|
|
50
|
+
if path is None:
|
|
51
|
+
continue
|
|
52
|
+
candidates.append(path)
|
|
53
|
+
if "astreum" not in path.parts:
|
|
54
|
+
return path
|
|
55
|
+
|
|
56
|
+
if candidates:
|
|
57
|
+
return candidates[0]
|
|
58
|
+
return pathlib.Path.cwd()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _derive_instance_id() -> str:
|
|
62
|
+
return _hash_path(_find_caller_path())[:16]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _log_root(org: str, product: str, instance_id: str) -> pathlib.Path:
|
|
66
|
+
"""Resolve the base directory for logs using platform defaults."""
|
|
67
|
+
if platform.system() == "Windows":
|
|
68
|
+
base = os.getenv("LOCALAPPDATA") or str(pathlib.Path.home())
|
|
69
|
+
return pathlib.Path(base) / org / product / "logs" / instance_id
|
|
70
|
+
|
|
71
|
+
xdg_state = os.getenv("XDG_STATE_HOME")
|
|
72
|
+
base_path = pathlib.Path(xdg_state) if xdg_state else pathlib.Path.home() / ".local" / "state"
|
|
73
|
+
return base_path / org / product / "logs" / instance_id
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class JSONFormatter(logging.Formatter):
|
|
77
|
+
"""Log record formatter that emits JSON objects per line."""
|
|
78
|
+
|
|
79
|
+
def format(self, record: logging.LogRecord) -> str: # type: ignore[override]
|
|
80
|
+
payload: Dict[str, Any] = {
|
|
81
|
+
"ts": datetime.fromtimestamp(record.created, tz=timezone.utc).isoformat(),
|
|
82
|
+
"level": record.levelname,
|
|
83
|
+
"logger": record.name,
|
|
84
|
+
"msg": record.getMessage(),
|
|
85
|
+
"pid": record.process,
|
|
86
|
+
"thread": record.threadName,
|
|
87
|
+
"module": record.module,
|
|
88
|
+
"func": record.funcName,
|
|
89
|
+
"instance_id": getattr(record, "instance_id", None),
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for key, value in record.__dict__.items():
|
|
93
|
+
if key in payload or key.startswith(("_", "msecs", "relativeCreated")):
|
|
94
|
+
continue
|
|
95
|
+
try:
|
|
96
|
+
json.dumps(value)
|
|
97
|
+
except Exception:
|
|
98
|
+
continue
|
|
99
|
+
payload[key] = value
|
|
100
|
+
|
|
101
|
+
return json.dumps(payload, ensure_ascii=False)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _gzip_rotator(src: str, dst: str) -> None:
|
|
105
|
+
"""Rotate the log file by gzipping it and removing the original."""
|
|
106
|
+
with open(src, "rb") as source, gzip.open(f"{dst}.gz", "wb") as target:
|
|
107
|
+
shutil.copyfileobj(source, target)
|
|
108
|
+
os.remove(src)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _namer(default_name: str) -> str:
|
|
112
|
+
"""Custom name for rotated logs: node-YYYY-MM-DD.log."""
|
|
113
|
+
path = pathlib.Path(default_name)
|
|
114
|
+
parent = path.parent
|
|
115
|
+
name = path.name
|
|
116
|
+
fragments = name.split(".log.")
|
|
117
|
+
if len(fragments) != 2:
|
|
118
|
+
return default_name
|
|
119
|
+
stem, date_part = fragments
|
|
120
|
+
return str(parent / f"{stem}-{date_part}.log")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _human_line(record: logging.LogRecord) -> str:
|
|
124
|
+
"""Format a record as a concise human-readable line."""
|
|
125
|
+
dt = datetime.fromtimestamp(record.created, tz=timezone.utc)
|
|
126
|
+
stamp = f"{dt:%Y-%m-%d}-{dt:%S}-{dt:%M}"
|
|
127
|
+
return f"[{stamp}] [{record.levelname.lower()}] {record.getMessage()}"
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class HumanFormatter(logging.Formatter):
|
|
131
|
+
"""Simple formatter for optional verbose console output."""
|
|
132
|
+
|
|
133
|
+
def format(self, record: logging.LogRecord) -> str: # type: ignore[override]
|
|
134
|
+
return _human_line(record)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _shutdown_listener(listener: logging.handlers.QueueListener, handlers: list[logging.Handler]) -> None:
|
|
138
|
+
"""Stop the queue listener and close handlers on interpreter exit."""
|
|
139
|
+
try:
|
|
140
|
+
listener.stop()
|
|
141
|
+
except Exception:
|
|
142
|
+
pass
|
|
143
|
+
finally:
|
|
144
|
+
for handler in handlers:
|
|
145
|
+
try:
|
|
146
|
+
handler.close()
|
|
147
|
+
except Exception:
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def logging_setup(config: dict) -> logging.LoggerAdapter:
|
|
152
|
+
"""Configure logging according to the runtime config and return an adapter."""
|
|
153
|
+
if config is None:
|
|
154
|
+
config = {}
|
|
155
|
+
elif not isinstance(config, dict):
|
|
156
|
+
config = dict(config)
|
|
157
|
+
|
|
158
|
+
org = _ORG_NAME
|
|
159
|
+
product = _PRODUCT_NAME
|
|
160
|
+
instance_id = _derive_instance_id()
|
|
161
|
+
|
|
162
|
+
retention_value = config.get("retention_days")
|
|
163
|
+
retention_days = int(retention_value) if retention_value is not None else 90
|
|
164
|
+
|
|
165
|
+
verbose = bool(config.get("verbose", False))
|
|
166
|
+
|
|
167
|
+
log_dir = _log_root(org, product, instance_id)
|
|
168
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
169
|
+
|
|
170
|
+
base_file = log_dir / "node.log"
|
|
171
|
+
file_handler = logging.handlers.TimedRotatingFileHandler(
|
|
172
|
+
filename=str(base_file),
|
|
173
|
+
when="midnight",
|
|
174
|
+
interval=1,
|
|
175
|
+
backupCount=max(retention_days, 0),
|
|
176
|
+
utc=True,
|
|
177
|
+
encoding="utf-8",
|
|
178
|
+
delay=True,
|
|
179
|
+
)
|
|
180
|
+
file_handler.setFormatter(JSONFormatter())
|
|
181
|
+
file_handler.rotator = _gzip_rotator
|
|
182
|
+
file_handler.namer = _namer
|
|
183
|
+
|
|
184
|
+
handler_list: list[logging.Handler] = [file_handler]
|
|
185
|
+
|
|
186
|
+
if verbose:
|
|
187
|
+
console_handler = logging.StreamHandler()
|
|
188
|
+
console_handler.setLevel(logging.INFO)
|
|
189
|
+
console_handler.setFormatter(HumanFormatter())
|
|
190
|
+
handler_list.append(console_handler)
|
|
191
|
+
|
|
192
|
+
log_queue: queue.Queue[logging.LogRecord] = queue.Queue(-1)
|
|
193
|
+
queue_handler = logging.handlers.QueueHandler(log_queue)
|
|
194
|
+
|
|
195
|
+
base_logger = logging.getLogger(f"{product}.{instance_id}")
|
|
196
|
+
base_logger.setLevel(logging.INFO)
|
|
197
|
+
base_logger.handlers.clear()
|
|
198
|
+
base_logger.propagate = False
|
|
199
|
+
base_logger.addHandler(queue_handler)
|
|
200
|
+
|
|
201
|
+
listener = logging.handlers.QueueListener(
|
|
202
|
+
log_queue, *handler_list, respect_handler_level=True
|
|
203
|
+
)
|
|
204
|
+
listener.daemon = True
|
|
205
|
+
listener.start()
|
|
206
|
+
atexit.register(_shutdown_listener, listener, handler_list)
|
|
207
|
+
|
|
208
|
+
adapter = logging.LoggerAdapter(base_logger, {"instance_id": instance_id})
|
|
209
|
+
setattr(adapter, "_queue_listener", listener)
|
|
210
|
+
setattr(adapter, "_handlers", handler_list)
|
|
211
|
+
|
|
212
|
+
return adapter
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
__all__ = [
|
|
216
|
+
"HumanFormatter",
|
|
217
|
+
"JSONFormatter",
|
|
218
|
+
"logging_setup",
|
|
219
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.61
|
|
4
4
|
Summary: Python library to interact with the Astreum blockchain and its Lispeum virtual machine.
|
|
5
5
|
Author-email: "Roy R. O. Okello" <roy@stelar.xyz>
|
|
6
6
|
Project-URL: Homepage, https://github.com/astreum/lib
|
|
@@ -35,6 +35,8 @@ When initializing an `astreum.Node`, pass a dictionary with any of the options b
|
|
|
35
35
|
| `validation_secret_key` | hex string | `None` | X25519 private key that lets the node participate in the validation route. Leave unset for a non‑validator node. |
|
|
36
36
|
| `storage_path` | string | `None` | Directory where objects are persisted. If *None*, the node uses an in‑memory store. |
|
|
37
37
|
| `storage_get_relay_timeout` | float | `5` | Seconds to wait for an object requested from peers before timing‑out. |
|
|
38
|
+
| `logging_retention` | int | `90` | Number of days to keep rotated log files (daily gzip). |
|
|
39
|
+
| `verbose` | bool | `False` | When **True**, also mirror JSON logs to stdout with a human-readable format. |
|
|
38
40
|
|
|
39
41
|
### Networking
|
|
40
42
|
|
|
@@ -136,6 +138,17 @@ except ParseError as e:
|
|
|
136
138
|
|
|
137
139
|
---
|
|
138
140
|
|
|
141
|
+
|
|
142
|
+
## Logging
|
|
143
|
+
|
|
144
|
+
Every `Node` instance wires up structured logging automatically:
|
|
145
|
+
|
|
146
|
+
- Logs land in per-instance files named `node.log` under `%LOCALAPPDATA%\Astreum\lib-py\logs/<instance_id>` on Windows and `$XDG_STATE_HOME` (or `~/.local/state`)/`Astreum/lib-py/logs/<instance_id>` on other platforms. The `<instance_id>` is the first 16 hex characters of a BLAKE3 hash of the caller's file path, so running the node from different entry points keeps their logs isolated.
|
|
147
|
+
- Files rotate at midnight UTC with gzip compression (`node-YYYY-MM-DD.log.gz`) and retain 90 days by default. Override via `config["logging_retention"]`.
|
|
148
|
+
- Each event is a single JSON line containing timestamp, level, logger, message, process/thread info, module/function, and the derived `instance_id`.
|
|
149
|
+
- Set `config["verbose"] = True` to mirror logs to stdout in a human-friendly format like `[2025-04-13-42-59] [info] Starting Astreum Node`.
|
|
150
|
+
- The very first entry emitted is the banner `Starting Astreum Node`, signalling that the logging pipeline is live before other subsystems spin up.
|
|
151
|
+
|
|
139
152
|
## Testing
|
|
140
153
|
|
|
141
154
|
```bash
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
astreum/__init__.py,sha256=9tzA27B_eG5wRF1SAWJIV7xTmCcR1QFc123b_cvFOa4,345
|
|
2
|
+
astreum/_node.py,sha256=S-_NsRVuMpcFxxG6ZD_C4sZU9ms6JueD7ZJKHpBSMiw,6997
|
|
3
|
+
astreum/format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
|
|
4
|
+
astreum/node.py,sha256=MmlK3jaANTMB3ZAxR8IaSc82OS9meJmVawYIVURADbg,39689
|
|
5
|
+
astreum/_communication/__init__.py,sha256=XJui0yOcfAur4HKt-8sSRlwB-MSU1rchkuOAY-nKDOE,207
|
|
6
|
+
astreum/_communication/message.py,sha256=Wl1IITj7eY9_q0IOT4J7c5gsjS1bF51CH7GcSSuu5OM,3327
|
|
7
|
+
astreum/_communication/peer.py,sha256=CbqkyCwhFCiC2spd1-KjNdeVGNjjt2ECVs8uHot-ETI,875
|
|
8
|
+
astreum/_communication/ping.py,sha256=u_DQTZJsbMdYiDDqjdZDsLaN5na2m9WZjVeEM3zq9_Y,955
|
|
9
|
+
astreum/_communication/route.py,sha256=Dqw8utefBeesZ311Nyizb7PO-g5dl26AoIUavttojHA,4037
|
|
10
|
+
astreum/_communication/setup.py,sha256=EN2GyVfGlVtkSHMhZWwJN33y-Ycfdvq9tjr38Myrmqg,11739
|
|
11
|
+
astreum/_communication/util.py,sha256=bJ3td3naDzmCelAJQpLwiDMoRBkijQl9YLROjsWyOrI,1256
|
|
12
|
+
astreum/_consensus/__init__.py,sha256=gOCpvnIeO17CGjUGr0odaKNvGEggmDRXfT5IuyrYtcM,376
|
|
13
|
+
astreum/_consensus/account.py,sha256=ClMB1e07ky5Wf7BwR4yhEjTSaWK2wiCmpvzio9AsZAY,3295
|
|
14
|
+
astreum/_consensus/accounts.py,sha256=zGq2BCMJPtD_lzcj4jqMzB2Foc3ptxXSPhc9zypB1T0,1106
|
|
15
|
+
astreum/_consensus/block.py,sha256=UfnB0JdzyDpC6BlNRRnj6yfWWzK3640BZflCRrwoqM4,12088
|
|
16
|
+
astreum/_consensus/chain.py,sha256=WwUeLrdg7uj--ZsUxse6xFlzO2QeQQggyKSL49KhfU0,2768
|
|
17
|
+
astreum/_consensus/fork.py,sha256=dK5DtT9hWCj_rQs6MS1c1bcGBbkgVTBPIOudYbqS9vw,3825
|
|
18
|
+
astreum/_consensus/genesis.py,sha256=YOzEEcpH5lQUdRNz1P8cfeddh-IJzjTbOiVKrEPHXPg,2506
|
|
19
|
+
astreum/_consensus/receipt.py,sha256=woUZmfqZIj6cEOFgM2wnh_tTb7u5IBqJcXdEIaIIAAM,4537
|
|
20
|
+
astreum/_consensus/setup.py,sha256=KHW2KzHRgCMLWaJNV2utosKdk7nxjI5aF9ie7jctgcU,4257
|
|
21
|
+
astreum/_consensus/transaction.py,sha256=KE3xcs0KkZQKTh-yr7DDsTMDIS82mpTQBJ_SZDZcy0g,7844
|
|
22
|
+
astreum/_consensus/workers/__init__.py,sha256=bS5FjbevbIR5FHbVGnT4Jli17VIld_5auemRw4CaHFU,278
|
|
23
|
+
astreum/_consensus/workers/discovery.py,sha256=X1yjKGjLSApMJ9mgWbnc7N21ALD09khDf-in-M45Mis,1683
|
|
24
|
+
astreum/_consensus/workers/validation.py,sha256=ftlwTDocwrvCk_BAicrOJgm3deZHgwjN_gn5r-gWE_0,4900
|
|
25
|
+
astreum/_consensus/workers/verify.py,sha256=wNkfh5qMARew79B-yyGL2UiExaSoGpOIq0fXUkDzpdw,1925
|
|
26
|
+
astreum/_lispeum/__init__.py,sha256=LAy2Z-gBBQlByBHRGUKaaQrOB7QzFEEyGRtInmwTpfU,304
|
|
27
|
+
astreum/_lispeum/environment.py,sha256=pJ0rjp9GoQxHhDiPIVei0jP7dZ_Pznso2O_tpp94-Ik,328
|
|
28
|
+
astreum/_lispeum/expression.py,sha256=AJRSax65fKUb1v-fDrgJnKQOFbQVzO_XTSQ-qgECkcI,6797
|
|
29
|
+
astreum/_lispeum/high_evaluation.py,sha256=Z0iSlx4IduhXwWghyflVpM1alKWOLAelqWvthe9rnhY,9554
|
|
30
|
+
astreum/_lispeum/low_evaluation.py,sha256=j4QaUhBUCSdZVcVngQ__gUJL3FxvzyzEIcIox2J50B0,4538
|
|
31
|
+
astreum/_lispeum/meter.py,sha256=5q2PFW7_jmgKVM1-vwE4RRjMfPEthUA4iu1CwR-Axws,505
|
|
32
|
+
astreum/_lispeum/parser.py,sha256=Z_Y0Sax0rPh8JcIo19-iNDQoc5GTdGQkmfFyLpCB4bw,1757
|
|
33
|
+
astreum/_lispeum/tokenizer.py,sha256=P68uIj4aPKzjuCJ85jfzRi67QztpuXIOC1vvLQueBI4,552
|
|
34
|
+
astreum/_storage/__init__.py,sha256=14C37U3MC52oGWIp99tCC6mfWZPYBK9moapl0sXbTHI,104
|
|
35
|
+
astreum/_storage/atom.py,sha256=14LKD-lYsHB0wjfCYrWzXEs-doalJuEwdMb9zuIZDw0,3106
|
|
36
|
+
astreum/_storage/patricia.py,sha256=VPrTAE8aOvHCrY1dzrJ8IObbpEvL8bOefkp1YfLjeMM,16385
|
|
37
|
+
astreum/_storage/setup.py,sha256=sgBrYUn2ljs-ntsliDyKa2KugZrLJwlqOc2Ikg_3WPs,1238
|
|
38
|
+
astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
+
astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
|
|
40
|
+
astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
|
|
41
|
+
astreum/crypto/wesolowski.py,sha256=SUgGXW3Id07dJtWzDcs4dluIhjqbRWQ8YWjn_mK78AQ,4092
|
|
42
|
+
astreum/crypto/x25519.py,sha256=i29v4BmwKRcbz9E7NKqFDQyxzFtJUqN0St9jd7GS1uA,1137
|
|
43
|
+
astreum/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
+
astreum/models/block.py,sha256=_dgas0zW9OLFV7C1Bo-laxa102klqpJrCAG3DnwQ51U,18092
|
|
45
|
+
astreum/models/merkle.py,sha256=lvWJa9nmrBL0n_2h_uNqpB_9a5s5Hn1FceRLx0IZIVQ,6778
|
|
46
|
+
astreum/models/patricia.py,sha256=ohmXrcaz7Ae561tyC4u4iPOkQPkKr8N0IWJek4upFIg,13392
|
|
47
|
+
astreum/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
+
astreum/storage/object.py,sha256=knFlvw_tpcC4twSu1DGNpHX31wlANN8E5dgEqIfU--Q,2041
|
|
49
|
+
astreum/storage/setup.py,sha256=1-9ztEFI_BvRDvAA0lAn4mFya8iq65THTArlj--M3Hg,626
|
|
50
|
+
astreum/utils/bytes.py,sha256=9QTWC2JCdwWLB5R2mPtmjPro0IUzE58DL3uEul4AheE,846
|
|
51
|
+
astreum/utils/integer.py,sha256=iQt-klWOYVghu_NOT341MmHbOle4FDT3by4PNKNXscg,736
|
|
52
|
+
astreum/utils/logging.py,sha256=mRDtWSCj8vKt58WGKLNSkK9Oa0graNVSoS8URby4Q9g,6684
|
|
53
|
+
astreum-0.2.61.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
54
|
+
astreum-0.2.61.dist-info/METADATA,sha256=lZdmBEvNYJxK5iWuYpIXo5PUX8zOqfqMx8n7YRHhvvY,7726
|
|
55
|
+
astreum-0.2.61.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
56
|
+
astreum-0.2.61.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
57
|
+
astreum-0.2.61.dist-info/RECORD,,
|
astreum-0.2.41.dist-info/RECORD
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
astreum/__init__.py,sha256=9tzA27B_eG5wRF1SAWJIV7xTmCcR1QFc123b_cvFOa4,345
|
|
2
|
-
astreum/_node.py,sha256=3fpfULVs3MrPBR-ymlvPyuZMi8lv0a8JBnxPb2oFOTU,2214
|
|
3
|
-
astreum/format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
|
|
4
|
-
astreum/node.py,sha256=MmlK3jaANTMB3ZAxR8IaSc82OS9meJmVawYIVURADbg,39689
|
|
5
|
-
astreum/_communication/__init__.py,sha256=XJui0yOcfAur4HKt-8sSRlwB-MSU1rchkuOAY-nKDOE,207
|
|
6
|
-
astreum/_communication/message.py,sha256=zNjUnt1roJRHMEoiLkcA7VK_TsHXok8PYEF7KTCqKnQ,3303
|
|
7
|
-
astreum/_communication/peer.py,sha256=DT2vJOzeLyyOj7vTDQ1u1lF5Vc7Epj0Hhie-YfDrzfA,425
|
|
8
|
-
astreum/_communication/ping.py,sha256=u_DQTZJsbMdYiDDqjdZDsLaN5na2m9WZjVeEM3zq9_Y,955
|
|
9
|
-
astreum/_communication/route.py,sha256=fbVXY0xF3O-k7dY9TuCsr6_XxD3m7Cb9ugVacQZ6GSk,2490
|
|
10
|
-
astreum/_communication/setup.py,sha256=TzXpc8dajV31BJhHQMMcb5UdaFrxb1xlYSj58vc_5mg,9072
|
|
11
|
-
astreum/_communication/util.py,sha256=bJ3td3naDzmCelAJQpLwiDMoRBkijQl9YLROjsWyOrI,1256
|
|
12
|
-
astreum/_consensus/__init__.py,sha256=gOCpvnIeO17CGjUGr0odaKNvGEggmDRXfT5IuyrYtcM,376
|
|
13
|
-
astreum/_consensus/account.py,sha256=d95h5c8kvmLD4CCyGRvaTJRQK7AESKrqDG8bCdbZOKg,5614
|
|
14
|
-
astreum/_consensus/accounts.py,sha256=NaLKDafsfq9SgFMtrYQpvAO7o0XbEwAIRhFl0dkY_Dk,2277
|
|
15
|
-
astreum/_consensus/block.py,sha256=v6U2y8br9PVKGn0Q8fLVOtEODlXayPtEd_Wqprem_TU,12358
|
|
16
|
-
astreum/_consensus/chain.py,sha256=WwUeLrdg7uj--ZsUxse6xFlzO2QeQQggyKSL49KhfU0,2768
|
|
17
|
-
astreum/_consensus/fork.py,sha256=dK5DtT9hWCj_rQs6MS1c1bcGBbkgVTBPIOudYbqS9vw,3825
|
|
18
|
-
astreum/_consensus/genesis.py,sha256=Xe9LA58cBz_IoutSJrtjeGDuFo0W-MVrWMkSdEwAVog,4760
|
|
19
|
-
astreum/_consensus/receipt.py,sha256=GPLspqVJHnyBr1cKmBoClsJyeEUecYmg3_acz4L4rRo,6031
|
|
20
|
-
astreum/_consensus/setup.py,sha256=agwqfOemdLqE0Z1zrPV2XHVmZ9sAxp8Bh4k6e2u-t8w,2385
|
|
21
|
-
astreum/_consensus/transaction.py,sha256=LK4oDe9EepOfzLxeXc19fEFDBoxY-aj_v-nsuRyET8g,6490
|
|
22
|
-
astreum/_consensus/workers/__init__.py,sha256=bS5FjbevbIR5FHbVGnT4Jli17VIld_5auemRw4CaHFU,278
|
|
23
|
-
astreum/_consensus/workers/discovery.py,sha256=X1yjKGjLSApMJ9mgWbnc7N21ALD09khDf-in-M45Mis,1683
|
|
24
|
-
astreum/_consensus/workers/validation.py,sha256=WcHLOs2NLMTrJpErghBXWeW2aqtX3-xGPo-HcySdEZ8,4814
|
|
25
|
-
astreum/_consensus/workers/verify.py,sha256=uqmf2UICj_eBFeGDpGyzKQLtz9qeCbOtz5euwNqkZmw,1924
|
|
26
|
-
astreum/_lispeum/__init__.py,sha256=LAy2Z-gBBQlByBHRGUKaaQrOB7QzFEEyGRtInmwTpfU,304
|
|
27
|
-
astreum/_lispeum/environment.py,sha256=pJ0rjp9GoQxHhDiPIVei0jP7dZ_Pznso2O_tpp94-Ik,328
|
|
28
|
-
astreum/_lispeum/expression.py,sha256=io8tbCer_1TJee77yRbcNI5q-DPFGa8xZiC80tGvRRQ,1063
|
|
29
|
-
astreum/_lispeum/high_evaluation.py,sha256=7MwIeVZMPumYvKXn6Lkn-GrZhRNB6MjnUUWdiYT7Ei0,7952
|
|
30
|
-
astreum/_lispeum/low_evaluation.py,sha256=HgyCSAmL5K5SKq3Xw_BtbTZZUJbMg4-bVZW-A12glQ0,4373
|
|
31
|
-
astreum/_lispeum/meter.py,sha256=5q2PFW7_jmgKVM1-vwE4RRjMfPEthUA4iu1CwR-Axws,505
|
|
32
|
-
astreum/_lispeum/parser.py,sha256=WOW3sSZWkIzPEy3fYTyl0lrtkMxHL9zRrNSYztPDemQ,2271
|
|
33
|
-
astreum/_lispeum/tokenizer.py,sha256=P68uIj4aPKzjuCJ85jfzRi67QztpuXIOC1vvLQueBI4,552
|
|
34
|
-
astreum/_storage/__init__.py,sha256=EmKZNAZmo3UVE3ekOOuckwFnBVjpa0Sy8Oxg72Lgdxc,53
|
|
35
|
-
astreum/_storage/atom.py,sha256=YFjvfMhniInch13iaKGpw4CCxxgyWonniryb-Rfse4A,4177
|
|
36
|
-
astreum/_storage/patricia.py,sha256=Eh8AO2_J8WCai4kyuML_0Jb_zntgGlq-VPljnSjss10,14851
|
|
37
|
-
astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
|
|
39
|
-
astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
|
|
40
|
-
astreum/crypto/wesolowski.py,sha256=SUgGXW3Id07dJtWzDcs4dluIhjqbRWQ8YWjn_mK78AQ,4092
|
|
41
|
-
astreum/crypto/x25519.py,sha256=i29v4BmwKRcbz9E7NKqFDQyxzFtJUqN0St9jd7GS1uA,1137
|
|
42
|
-
astreum/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
-
astreum/models/block.py,sha256=7qKUhOpL26NiiLDq_ff7mJCNrbxWb_9jPTtMtjemy3Y,18126
|
|
44
|
-
astreum/models/merkle.py,sha256=lvWJa9nmrBL0n_2h_uNqpB_9a5s5Hn1FceRLx0IZIVQ,6778
|
|
45
|
-
astreum/models/patricia.py,sha256=ohmXrcaz7Ae561tyC4u4iPOkQPkKr8N0IWJek4upFIg,13392
|
|
46
|
-
astreum/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
|
-
astreum/storage/object.py,sha256=knFlvw_tpcC4twSu1DGNpHX31wlANN8E5dgEqIfU--Q,2041
|
|
48
|
-
astreum/storage/setup.py,sha256=1-9ztEFI_BvRDvAA0lAn4mFya8iq65THTArlj--M3Hg,626
|
|
49
|
-
astreum-0.2.41.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
50
|
-
astreum-0.2.41.dist-info/METADATA,sha256=03v5FuUofHssnDaviuCFvqWB1p3hz6lqvhM1t9HFhas,6181
|
|
51
|
-
astreum-0.2.41.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
52
|
-
astreum-0.2.41.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
53
|
-
astreum-0.2.41.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|