astreum 0.2.37__py3-none-any.whl → 0.2.39__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.
Potentially problematic release.
This version of astreum might be problematic. Click here for more details.
- astreum/_communication/setup.py +14 -5
- astreum/{_validation → _consensus}/__init__.py +6 -4
- astreum/{_validation → _consensus}/setup.py +70 -2
- astreum/_consensus/transaction.py +172 -0
- astreum/_node.py +3 -3
- {astreum-0.2.37.dist-info → astreum-0.2.39.dist-info}/METADATA +1 -1
- {astreum-0.2.37.dist-info → astreum-0.2.39.dist-info}/RECORD +14 -13
- /astreum/{_validation → _consensus}/block.py +0 -0
- /astreum/{_validation → _consensus}/chain.py +0 -0
- /astreum/{_validation → _consensus}/fork.py +0 -0
- /astreum/{_validation → _consensus}/genesis.py +0 -0
- {astreum-0.2.37.dist-info → astreum-0.2.39.dist-info}/WHEEL +0 -0
- {astreum-0.2.37.dist-info → astreum-0.2.39.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.37.dist-info → astreum-0.2.39.dist-info}/top_level.txt +0 -0
astreum/_communication/setup.py
CHANGED
|
@@ -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
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
from .block import Block
|
|
2
2
|
from .chain import Chain
|
|
3
3
|
from .fork import Fork
|
|
4
|
-
from .
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
from .transaction import Transaction
|
|
5
|
+
from .setup import consensus_setup
|
|
6
|
+
|
|
7
|
+
|
|
7
8
|
__all__ = [
|
|
8
9
|
"Block",
|
|
9
10
|
"Chain",
|
|
10
11
|
"Fork",
|
|
11
|
-
"
|
|
12
|
+
"Transaction",
|
|
13
|
+
"consensus_setup",
|
|
12
14
|
]
|
|
@@ -2,16 +2,27 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import threading
|
|
4
4
|
import time
|
|
5
|
-
from queue import
|
|
5
|
+
from queue import Empty, Queue
|
|
6
6
|
from typing import Any, Dict, Optional, Tuple
|
|
7
7
|
|
|
8
8
|
from .block import Block
|
|
9
9
|
from .chain import Chain
|
|
10
10
|
from .fork import Fork
|
|
11
|
+
from .transaction import Transaction
|
|
11
12
|
from .._storage.atom import ZERO32, Atom
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
def
|
|
15
|
+
def current_validator(node: Any) -> bytes:
|
|
16
|
+
"""Return the current validator identifier. Override downstream."""
|
|
17
|
+
raise NotImplementedError("current_validator must be implemented by the host node")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def apply_transaction(node: Any, block: object, transaction_hash: bytes) -> None:
|
|
21
|
+
"""Apply transaction to the candidate block. Override downstream."""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def consensus_setup(node: Any) -> None:
|
|
15
26
|
# Shared state
|
|
16
27
|
node.validation_lock = getattr(node, "validation_lock", threading.RLock())
|
|
17
28
|
|
|
@@ -21,6 +32,10 @@ def validation_setup(node: Any) -> None:
|
|
|
21
32
|
node.chains = getattr(node, "chains", {})
|
|
22
33
|
node.forks = getattr(node, "forks", {})
|
|
23
34
|
|
|
35
|
+
# Pending transactions queue (hash-only entries)
|
|
36
|
+
node._validation_transaction_queue = getattr(
|
|
37
|
+
node, "_validation_transaction_queue", Queue()
|
|
38
|
+
)
|
|
24
39
|
# Single work queue of grouped items: (latest_block_hash, set(peer_ids))
|
|
25
40
|
node._validation_verify_queue = getattr(
|
|
26
41
|
node, "_validation_verify_queue", Queue()
|
|
@@ -29,6 +44,14 @@ def validation_setup(node: Any) -> None:
|
|
|
29
44
|
node, "_validation_stop_event", threading.Event()
|
|
30
45
|
)
|
|
31
46
|
|
|
47
|
+
def enqueue_transaction_hash(tx_hash: bytes) -> None:
|
|
48
|
+
"""Schedule a transaction hash for validation processing."""
|
|
49
|
+
if not isinstance(tx_hash, (bytes, bytearray)):
|
|
50
|
+
raise TypeError("transaction hash must be bytes-like")
|
|
51
|
+
node._validation_transaction_queue.put(bytes(tx_hash))
|
|
52
|
+
|
|
53
|
+
node.enqueue_transaction_hash = enqueue_transaction_hash
|
|
54
|
+
|
|
32
55
|
def _process_peers_latest_block(latest_block_hash: bytes, peer_ids: set[Any]) -> None:
|
|
33
56
|
"""Assign a peer to a fork for its latest block without merging forks.
|
|
34
57
|
|
|
@@ -130,6 +153,46 @@ def validation_setup(node: Any) -> None:
|
|
|
130
153
|
except Exception:
|
|
131
154
|
pass
|
|
132
155
|
|
|
156
|
+
def _validation_worker() -> None:
|
|
157
|
+
"""Consume pending transactions when scheduled to validate."""
|
|
158
|
+
stop = node._validation_stop_event
|
|
159
|
+
while not stop.is_set():
|
|
160
|
+
validation_public_key = getattr(node, "validation_public_key", None)
|
|
161
|
+
if not validation_public_key:
|
|
162
|
+
time.sleep(0.5)
|
|
163
|
+
continue
|
|
164
|
+
|
|
165
|
+
scheduled_validator = current_validator(node)
|
|
166
|
+
|
|
167
|
+
if scheduled_validator != validation_public_key:
|
|
168
|
+
time.sleep(0.5)
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
current_hash = node._validation_transaction_queue.get_nowait()
|
|
173
|
+
except Empty:
|
|
174
|
+
time.sleep(0.1)
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
new_block = Block()
|
|
178
|
+
new_block.validator_public_key = getattr(node, "validation_public_key", None)
|
|
179
|
+
|
|
180
|
+
while True:
|
|
181
|
+
try:
|
|
182
|
+
apply_transaction(node, new_block, current_hash)
|
|
183
|
+
except NotImplementedError:
|
|
184
|
+
node._validation_transaction_queue.put(current_hash)
|
|
185
|
+
time.sleep(0.5)
|
|
186
|
+
break
|
|
187
|
+
except Exception:
|
|
188
|
+
# Skip problematic transaction; leave block as-is.
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
current_hash = node._validation_transaction_queue.get_nowait()
|
|
193
|
+
except Empty:
|
|
194
|
+
break
|
|
195
|
+
|
|
133
196
|
# Start workers as daemons
|
|
134
197
|
node.validation_discovery_thread = threading.Thread(
|
|
135
198
|
target=_discovery_worker, daemon=True, name="validation-discovery"
|
|
@@ -137,5 +200,10 @@ def validation_setup(node: Any) -> None:
|
|
|
137
200
|
node.validation_verify_thread = threading.Thread(
|
|
138
201
|
target=_verify_worker, daemon=True, name="validation-verify"
|
|
139
202
|
)
|
|
203
|
+
node.validation_worker_thread = threading.Thread(
|
|
204
|
+
target=_validation_worker, daemon=True, name="validation-worker"
|
|
205
|
+
)
|
|
140
206
|
node.validation_discovery_thread.start()
|
|
141
207
|
node.validation_verify_thread.start()
|
|
208
|
+
if getattr(node, "validation_secret_key", None):
|
|
209
|
+
node.validation_worker_thread.start()
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Callable, List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
from .._storage.atom import Atom, ZERO32
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _int_to_be_bytes(value: Optional[int]) -> bytes:
|
|
10
|
+
if value is None:
|
|
11
|
+
return b""
|
|
12
|
+
value = int(value)
|
|
13
|
+
if value == 0:
|
|
14
|
+
return b"\x00"
|
|
15
|
+
size = (value.bit_length() + 7) // 8
|
|
16
|
+
return value.to_bytes(size, "big")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _be_bytes_to_int(data: Optional[bytes]) -> int:
|
|
20
|
+
if not data:
|
|
21
|
+
return 0
|
|
22
|
+
return int.from_bytes(data, "big")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _make_typed_bytes(payload: bytes) -> Tuple[bytes, List[Atom]]:
|
|
26
|
+
value_atom = Atom.from_data(data=payload)
|
|
27
|
+
type_atom = Atom.from_data(data=b"byte", next_hash=value_atom.object_id())
|
|
28
|
+
return type_atom.object_id(), [value_atom, type_atom]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _make_list(child_ids: List[bytes]) -> Tuple[bytes, List[Atom]]:
|
|
32
|
+
atoms: List[Atom] = []
|
|
33
|
+
next_hash = ZERO32
|
|
34
|
+
chain: List[Atom] = []
|
|
35
|
+
for child_id in reversed(child_ids):
|
|
36
|
+
elem = Atom.from_data(data=child_id, next_hash=next_hash)
|
|
37
|
+
next_hash = elem.object_id()
|
|
38
|
+
chain.append(elem)
|
|
39
|
+
|
|
40
|
+
chain.reverse()
|
|
41
|
+
list_value = Atom.from_data(data=len(child_ids).to_bytes(8, "little"), next_hash=next_hash)
|
|
42
|
+
list_type = Atom.from_data(data=b"list", next_hash=list_value.object_id())
|
|
43
|
+
atoms.extend(chain)
|
|
44
|
+
atoms.append(list_value)
|
|
45
|
+
atoms.append(list_type)
|
|
46
|
+
return list_type.object_id(), atoms
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class Transaction:
|
|
51
|
+
amount: int
|
|
52
|
+
counter: int
|
|
53
|
+
data: bytes = b""
|
|
54
|
+
recipient: bytes = b""
|
|
55
|
+
sender: bytes = b""
|
|
56
|
+
signature: bytes = b""
|
|
57
|
+
|
|
58
|
+
def to_atom(self) -> Tuple[bytes, List[Atom]]:
|
|
59
|
+
"""Serialise the transaction, returning (object_id, atoms)."""
|
|
60
|
+
body_child_ids: List[bytes] = []
|
|
61
|
+
acc: List[Atom] = []
|
|
62
|
+
|
|
63
|
+
def emit(payload: bytes) -> None:
|
|
64
|
+
oid, atoms = _make_typed_bytes(payload)
|
|
65
|
+
body_child_ids.append(oid)
|
|
66
|
+
acc.extend(atoms)
|
|
67
|
+
|
|
68
|
+
emit(_int_to_be_bytes(self.amount))
|
|
69
|
+
emit(_int_to_be_bytes(self.counter))
|
|
70
|
+
emit(bytes(self.data))
|
|
71
|
+
emit(bytes(self.recipient))
|
|
72
|
+
emit(bytes(self.sender))
|
|
73
|
+
|
|
74
|
+
body_id, body_atoms = _make_list(body_child_ids)
|
|
75
|
+
acc.extend(body_atoms)
|
|
76
|
+
|
|
77
|
+
type_atom = Atom.from_data(data=b"transaction", next_hash=body_id)
|
|
78
|
+
signature_atom = Atom.from_data(data=bytes(self.signature))
|
|
79
|
+
|
|
80
|
+
top_list_id, top_atoms = _make_list(
|
|
81
|
+
[type_atom.object_id(), body_id, signature_atom.object_id()]
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
atoms: List[Atom] = acc
|
|
85
|
+
atoms.append(type_atom)
|
|
86
|
+
atoms.append(signature_atom)
|
|
87
|
+
atoms.extend(top_atoms)
|
|
88
|
+
return top_list_id, atoms
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def from_atom(
|
|
92
|
+
cls,
|
|
93
|
+
storage_get: Callable[[bytes], Optional[Atom]],
|
|
94
|
+
transaction_id: bytes,
|
|
95
|
+
) -> Transaction:
|
|
96
|
+
top_type_atom = storage_get(transaction_id)
|
|
97
|
+
if top_type_atom is None or top_type_atom.data != b"list":
|
|
98
|
+
raise ValueError("not a transaction (outer list missing)")
|
|
99
|
+
|
|
100
|
+
top_value_atom = storage_get(top_type_atom.next)
|
|
101
|
+
if top_value_atom is None:
|
|
102
|
+
raise ValueError("malformed transaction (outer value missing)")
|
|
103
|
+
|
|
104
|
+
head = top_value_atom.next
|
|
105
|
+
first_elem = storage_get(head)
|
|
106
|
+
if first_elem is None:
|
|
107
|
+
raise ValueError("malformed transaction (type element missing)")
|
|
108
|
+
|
|
109
|
+
type_atom_id = first_elem.data
|
|
110
|
+
type_atom = storage_get(type_atom_id)
|
|
111
|
+
if type_atom is None or type_atom.data != b"transaction":
|
|
112
|
+
raise ValueError("not a transaction (type mismatch)")
|
|
113
|
+
|
|
114
|
+
def read_list_entries(start: bytes) -> List[bytes]:
|
|
115
|
+
entries: List[bytes] = []
|
|
116
|
+
current = start if start != ZERO32 else b""
|
|
117
|
+
while current:
|
|
118
|
+
elem = storage_get(current)
|
|
119
|
+
if elem is None:
|
|
120
|
+
break
|
|
121
|
+
entries.append(elem.data)
|
|
122
|
+
nxt = elem.next
|
|
123
|
+
current = nxt if nxt != ZERO32 else b""
|
|
124
|
+
return entries
|
|
125
|
+
|
|
126
|
+
remainder_entries = read_list_entries(first_elem.next)
|
|
127
|
+
if len(remainder_entries) < 2:
|
|
128
|
+
raise ValueError("malformed transaction (body/signature missing)")
|
|
129
|
+
|
|
130
|
+
body_id, signature_atom_id = remainder_entries[0], remainder_entries[1]
|
|
131
|
+
|
|
132
|
+
body_type_atom = storage_get(body_id)
|
|
133
|
+
if body_type_atom is None or body_type_atom.data != b"list":
|
|
134
|
+
raise ValueError("malformed transaction body (type)")
|
|
135
|
+
|
|
136
|
+
body_value_atom = storage_get(body_type_atom.next)
|
|
137
|
+
if body_value_atom is None:
|
|
138
|
+
raise ValueError("malformed transaction body (value)")
|
|
139
|
+
|
|
140
|
+
body_entries = read_list_entries(body_value_atom.next)
|
|
141
|
+
if len(body_entries) < 5:
|
|
142
|
+
body_entries.extend([ZERO32] * (5 - len(body_entries)))
|
|
143
|
+
|
|
144
|
+
def read_typed_bytes(entry_id: bytes) -> bytes:
|
|
145
|
+
if not entry_id or entry_id == ZERO32:
|
|
146
|
+
return b""
|
|
147
|
+
elem = storage_get(entry_id)
|
|
148
|
+
if elem is None:
|
|
149
|
+
return b""
|
|
150
|
+
type_atom = storage_get(elem.data)
|
|
151
|
+
if type_atom is None or type_atom.data != b"byte":
|
|
152
|
+
return b""
|
|
153
|
+
value_atom = storage_get(type_atom.next)
|
|
154
|
+
return value_atom.data if value_atom is not None else b""
|
|
155
|
+
|
|
156
|
+
amount_bytes = read_typed_bytes(body_entries[0])
|
|
157
|
+
counter_bytes = read_typed_bytes(body_entries[1])
|
|
158
|
+
data_bytes = read_typed_bytes(body_entries[2])
|
|
159
|
+
recipient_bytes = read_typed_bytes(body_entries[3])
|
|
160
|
+
sender_bytes = read_typed_bytes(body_entries[4])
|
|
161
|
+
|
|
162
|
+
signature_atom = storage_get(signature_atom_id)
|
|
163
|
+
signature_bytes = signature_atom.data if signature_atom is not None else b""
|
|
164
|
+
|
|
165
|
+
return cls(
|
|
166
|
+
amount=_be_bytes_to_int(amount_bytes),
|
|
167
|
+
counter=_be_bytes_to_int(counter_bytes),
|
|
168
|
+
data=data_bytes,
|
|
169
|
+
recipient=recipient_bytes,
|
|
170
|
+
sender=sender_bytes,
|
|
171
|
+
signature=signature_bytes,
|
|
172
|
+
)
|
astreum/_node.py
CHANGED
|
@@ -25,9 +25,9 @@ class Node:
|
|
|
25
25
|
communication_setup(node=self, config=config)
|
|
26
26
|
except Exception:
|
|
27
27
|
pass
|
|
28
|
-
try:
|
|
29
|
-
from astreum.
|
|
30
|
-
|
|
28
|
+
try:
|
|
29
|
+
from astreum._consensus import consensus_setup # type: ignore
|
|
30
|
+
consensus_setup(node=self)
|
|
31
31
|
except Exception:
|
|
32
32
|
pass
|
|
33
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.39
|
|
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,11 +1,18 @@
|
|
|
1
1
|
astreum/__init__.py,sha256=9tzA27B_eG5wRF1SAWJIV7xTmCcR1QFc123b_cvFOa4,345
|
|
2
|
-
astreum/_node.py,sha256=
|
|
2
|
+
astreum/_node.py,sha256=3fpfULVs3MrPBR-ymlvPyuZMi8lv0a8JBnxPb2oFOTU,2214
|
|
3
3
|
astreum/format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
|
|
4
4
|
astreum/node.py,sha256=SuVm1b0QWl1FpDUaLRH1fiFYnXCrPs6qYeUQlPDae8w,38358
|
|
5
5
|
astreum/_communication/__init__.py,sha256=I6TVFC1KXtwwdCjKUkGjOhsLWfC7cECubjzqmm-SwRs,161
|
|
6
6
|
astreum/_communication/peer.py,sha256=DT2vJOzeLyyOj7vTDQ1u1lF5Vc7Epj0Hhie-YfDrzfA,425
|
|
7
7
|
astreum/_communication/route.py,sha256=enWT_1260LJq-L-zK-jtacQ8LbZGquNO9yj-9IglSXE,1232
|
|
8
|
-
astreum/_communication/setup.py,sha256=
|
|
8
|
+
astreum/_communication/setup.py,sha256=6KH144iaHNec9g4cvC8fcLIBY0dvx5OCjV5WVYKNcZo,3865
|
|
9
|
+
astreum/_consensus/__init__.py,sha256=EDwIjOABPYv1c8jL0ib1hd8CuNCovTVrdcwxIy_qhaU,241
|
|
10
|
+
astreum/_consensus/block.py,sha256=4ImViawnG0bhN-TiCk3F0byTlPm9U0l6PdSL53u3bsc,11171
|
|
11
|
+
astreum/_consensus/chain.py,sha256=lOFbz5z0AOeMLchQ2YPRSbIZIdQlnHqDyMJvgdwJ-Iw,2532
|
|
12
|
+
astreum/_consensus/fork.py,sha256=ZGTOVEhSiYJvvLvlC6FV8Zqe62uLTM-cSS3yKrKrLvA,3602
|
|
13
|
+
astreum/_consensus/genesis.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
astreum/_consensus/setup.py,sha256=ao9Vcuv8vUUn5yDAFBpjA_ffsmAv0pBeED0eYn997r0,8215
|
|
15
|
+
astreum/_consensus/transaction.py,sha256=LhMGQgXR4RxcEGu6m4aYsKAVhSX_bNt17jMtWaagnHc,5992
|
|
9
16
|
astreum/_lispeum/__init__.py,sha256=LAy2Z-gBBQlByBHRGUKaaQrOB7QzFEEyGRtInmwTpfU,304
|
|
10
17
|
astreum/_lispeum/environment.py,sha256=pJ0rjp9GoQxHhDiPIVei0jP7dZ_Pznso2O_tpp94-Ik,328
|
|
11
18
|
astreum/_lispeum/expression.py,sha256=io8tbCer_1TJee77yRbcNI5q-DPFGa8xZiC80tGvRRQ,1063
|
|
@@ -16,12 +23,6 @@ astreum/_lispeum/parser.py,sha256=WOW3sSZWkIzPEy3fYTyl0lrtkMxHL9zRrNSYztPDemQ,22
|
|
|
16
23
|
astreum/_lispeum/tokenizer.py,sha256=P68uIj4aPKzjuCJ85jfzRi67QztpuXIOC1vvLQueBI4,552
|
|
17
24
|
astreum/_storage/__init__.py,sha256=EmKZNAZmo3UVE3ekOOuckwFnBVjpa0Sy8Oxg72Lgdxc,53
|
|
18
25
|
astreum/_storage/atom.py,sha256=w0O_jw74nGhO0hgxFHk0RmkCIgHXHweBEOVULi7_dhQ,3652
|
|
19
|
-
astreum/_validation/__init__.py,sha256=E2-CITedO5bIHsYG2zMr3vwmV9asF3aRWh2V3bwJShY,189
|
|
20
|
-
astreum/_validation/block.py,sha256=4ImViawnG0bhN-TiCk3F0byTlPm9U0l6PdSL53u3bsc,11171
|
|
21
|
-
astreum/_validation/chain.py,sha256=lOFbz5z0AOeMLchQ2YPRSbIZIdQlnHqDyMJvgdwJ-Iw,2532
|
|
22
|
-
astreum/_validation/fork.py,sha256=ZGTOVEhSiYJvvLvlC6FV8Zqe62uLTM-cSS3yKrKrLvA,3602
|
|
23
|
-
astreum/_validation/genesis.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
-
astreum/_validation/setup.py,sha256=VSuCtLBZ3ieHHlJl3EkI5n4mEjRpgJ9hfKGxeGSrAVo,5592
|
|
25
26
|
astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
27
|
astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
|
|
27
28
|
astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
|
|
@@ -47,8 +48,8 @@ astreum/relay/setup.py,sha256=ynvGaJdlDtw_f5LLiow2Wo7IRzUjvgk8eSr1Sv4_zTg,2090
|
|
|
47
48
|
astreum/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
49
|
astreum/storage/object.py,sha256=knFlvw_tpcC4twSu1DGNpHX31wlANN8E5dgEqIfU--Q,2041
|
|
49
50
|
astreum/storage/setup.py,sha256=1-9ztEFI_BvRDvAA0lAn4mFya8iq65THTArlj--M3Hg,626
|
|
50
|
-
astreum-0.2.
|
|
51
|
-
astreum-0.2.
|
|
52
|
-
astreum-0.2.
|
|
53
|
-
astreum-0.2.
|
|
54
|
-
astreum-0.2.
|
|
51
|
+
astreum-0.2.39.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
52
|
+
astreum-0.2.39.dist-info/METADATA,sha256=htQXaHM7_zULw39odLaHu6wtU-W_sa5IXt0GlxEejGU,6181
|
|
53
|
+
astreum-0.2.39.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
54
|
+
astreum-0.2.39.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
55
|
+
astreum-0.2.39.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|