astreum 0.2.37__tar.gz → 0.2.38__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.
Potentially problematic release.
This version of astreum might be problematic. Click here for more details.
- {astreum-0.2.37/src/astreum.egg-info → astreum-0.2.38}/PKG-INFO +1 -1
- {astreum-0.2.37 → astreum-0.2.38}/pyproject.toml +1 -1
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_communication/setup.py +14 -5
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_validation/setup.py +81 -1
- {astreum-0.2.37 → astreum-0.2.38/src/astreum.egg-info}/PKG-INFO +1 -1
- {astreum-0.2.37 → astreum-0.2.38}/LICENSE +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/README.md +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/setup.cfg +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_communication/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_communication/peer.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_communication/route.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/environment.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/expression.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/high_evaluation.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/low_evaluation.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/meter.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/parser.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_lispeum/tokenizer.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_node.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_storage/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_storage/atom.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_validation/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_validation/block.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_validation/chain.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_validation/fork.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/_validation/genesis.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/crypto/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/crypto/ed25519.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/crypto/quadratic_form.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/crypto/wesolowski.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/crypto/x25519.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/format.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/lispeum/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/lispeum/environment.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/lispeum/expression.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/lispeum/parser.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/lispeum/tokenizer.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/account.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/accounts.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/block.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/merkle.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/message.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/patricia.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/models/transaction.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/node.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/relay/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/relay/peer.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/relay/route.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/relay/setup.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/storage/__init__.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/storage/object.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum/storage/setup.py +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum.egg-info/SOURCES.txt +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum.egg-info/dependency_links.txt +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum.egg-info/requires.txt +0 -0
- {astreum-0.2.37 → astreum-0.2.38}/src/astreum.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.38
|
|
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
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import socket, threading
|
|
2
2
|
from queue import Queue
|
|
3
3
|
from typing import Tuple, Optional
|
|
4
|
-
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
4
|
+
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
5
|
+
from cryptography.hazmat.primitives import serialization
|
|
5
6
|
from cryptography.hazmat.primitives.asymmetric.x25519 import (
|
|
6
7
|
X25519PrivateKey,
|
|
7
8
|
X25519PublicKey,
|
|
@@ -67,10 +68,18 @@ def communication_setup(node: "Node", config: dict):
|
|
|
67
68
|
|
|
68
69
|
# key loading
|
|
69
70
|
node.relay_secret_key = load_x25519(config.get('relay_secret_key'))
|
|
70
|
-
node.validation_secret_key = load_ed25519(config.get('validation_secret_key'))
|
|
71
|
-
|
|
72
|
-
# derive pubs + routes
|
|
73
|
-
node.relay_public_key = node.relay_secret_key.public_key()
|
|
71
|
+
node.validation_secret_key = load_ed25519(config.get('validation_secret_key'))
|
|
72
|
+
|
|
73
|
+
# derive pubs + routes
|
|
74
|
+
node.relay_public_key = node.relay_secret_key.public_key()
|
|
75
|
+
node.validation_public_key = (
|
|
76
|
+
node.validation_secret_key.public_key().public_bytes(
|
|
77
|
+
encoding=serialization.Encoding.Raw,
|
|
78
|
+
format=serialization.PublicFormat.Raw,
|
|
79
|
+
)
|
|
80
|
+
if node.validation_secret_key
|
|
81
|
+
else None
|
|
82
|
+
)
|
|
74
83
|
node.peer_route, node.validation_route = make_routes(
|
|
75
84
|
node.relay_public_key,
|
|
76
85
|
node.validation_secret_key
|
|
@@ -2,15 +2,38 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import threading
|
|
4
4
|
import time
|
|
5
|
-
from
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from queue import Empty, Queue
|
|
6
7
|
from typing import Any, Dict, Optional, Tuple
|
|
7
8
|
|
|
9
|
+
from cryptography.hazmat.primitives import serialization
|
|
10
|
+
|
|
8
11
|
from .block import Block
|
|
9
12
|
from .chain import Chain
|
|
10
13
|
from .fork import Fork
|
|
11
14
|
from .._storage.atom import ZERO32, Atom
|
|
12
15
|
|
|
13
16
|
|
|
17
|
+
@dataclass
|
|
18
|
+
class Transaction:
|
|
19
|
+
"""Lightweight transaction view for validation processing."""
|
|
20
|
+
|
|
21
|
+
recipient: bytes
|
|
22
|
+
sender: bytes
|
|
23
|
+
amount: int
|
|
24
|
+
counter: int
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def current_validator(node: Any) -> bytes:
|
|
28
|
+
"""Return the current validator identifier. Override downstream."""
|
|
29
|
+
raise NotImplementedError("current_validator must be implemented by the host node")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def apply_transaction(node: Any, block: object, transaction_hash: bytes) -> None:
|
|
33
|
+
"""Apply transaction to the candidate block. Override downstream."""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
14
37
|
def validation_setup(node: Any) -> None:
|
|
15
38
|
# Shared state
|
|
16
39
|
node.validation_lock = getattr(node, "validation_lock", threading.RLock())
|
|
@@ -21,6 +44,10 @@ def validation_setup(node: Any) -> None:
|
|
|
21
44
|
node.chains = getattr(node, "chains", {})
|
|
22
45
|
node.forks = getattr(node, "forks", {})
|
|
23
46
|
|
|
47
|
+
# Pending transactions queue (hash-only entries)
|
|
48
|
+
node._validation_transaction_queue = getattr(
|
|
49
|
+
node, "_validation_transaction_queue", Queue()
|
|
50
|
+
)
|
|
24
51
|
# Single work queue of grouped items: (latest_block_hash, set(peer_ids))
|
|
25
52
|
node._validation_verify_queue = getattr(
|
|
26
53
|
node, "_validation_verify_queue", Queue()
|
|
@@ -29,6 +56,14 @@ def validation_setup(node: Any) -> None:
|
|
|
29
56
|
node, "_validation_stop_event", threading.Event()
|
|
30
57
|
)
|
|
31
58
|
|
|
59
|
+
def enqueue_transaction_hash(tx_hash: bytes) -> None:
|
|
60
|
+
"""Schedule a transaction hash for validation processing."""
|
|
61
|
+
if not isinstance(tx_hash, (bytes, bytearray)):
|
|
62
|
+
raise TypeError("transaction hash must be bytes-like")
|
|
63
|
+
node._validation_transaction_queue.put(bytes(tx_hash))
|
|
64
|
+
|
|
65
|
+
node.enqueue_transaction_hash = enqueue_transaction_hash
|
|
66
|
+
|
|
32
67
|
def _process_peers_latest_block(latest_block_hash: bytes, peer_ids: set[Any]) -> None:
|
|
33
68
|
"""Assign a peer to a fork for its latest block without merging forks.
|
|
34
69
|
|
|
@@ -130,6 +165,46 @@ def validation_setup(node: Any) -> None:
|
|
|
130
165
|
except Exception:
|
|
131
166
|
pass
|
|
132
167
|
|
|
168
|
+
def _validation_worker() -> None:
|
|
169
|
+
"""Consume pending transactions when scheduled to validate."""
|
|
170
|
+
stop = node._validation_stop_event
|
|
171
|
+
while not stop.is_set():
|
|
172
|
+
validation_public_key = getattr(node, "validation_public_key", None)
|
|
173
|
+
if not validation_public_key:
|
|
174
|
+
time.sleep(0.5)
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
scheduled_validator = current_validator(node)
|
|
178
|
+
|
|
179
|
+
if scheduled_validator != validation_public_key:
|
|
180
|
+
time.sleep(0.5)
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
current_hash = node._validation_transaction_queue.get_nowait()
|
|
185
|
+
except Empty:
|
|
186
|
+
time.sleep(0.1)
|
|
187
|
+
continue
|
|
188
|
+
|
|
189
|
+
new_block = Block()
|
|
190
|
+
new_block.validator_public_key = getattr(node, "validation_public_key", None)
|
|
191
|
+
|
|
192
|
+
while True:
|
|
193
|
+
try:
|
|
194
|
+
apply_transaction(node, new_block, current_hash)
|
|
195
|
+
except NotImplementedError:
|
|
196
|
+
node._validation_transaction_queue.put(current_hash)
|
|
197
|
+
time.sleep(0.5)
|
|
198
|
+
break
|
|
199
|
+
except Exception:
|
|
200
|
+
# Skip problematic transaction; leave block as-is.
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
current_hash = node._validation_transaction_queue.get_nowait()
|
|
205
|
+
except Empty:
|
|
206
|
+
break
|
|
207
|
+
|
|
133
208
|
# Start workers as daemons
|
|
134
209
|
node.validation_discovery_thread = threading.Thread(
|
|
135
210
|
target=_discovery_worker, daemon=True, name="validation-discovery"
|
|
@@ -137,5 +212,10 @@ def validation_setup(node: Any) -> None:
|
|
|
137
212
|
node.validation_verify_thread = threading.Thread(
|
|
138
213
|
target=_verify_worker, daemon=True, name="validation-verify"
|
|
139
214
|
)
|
|
215
|
+
node.validation_worker_thread = threading.Thread(
|
|
216
|
+
target=_validation_worker, daemon=True, name="validation-worker"
|
|
217
|
+
)
|
|
140
218
|
node.validation_discovery_thread.start()
|
|
141
219
|
node.validation_verify_thread.start()
|
|
220
|
+
if getattr(node, "validation_secret_key", None):
|
|
221
|
+
node.validation_worker_thread.start()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.38
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|