astreum 0.2.42__py3-none-any.whl → 0.2.44__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/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 +1 -1
- astreum/_consensus/block.py +2 -2
- astreum/_consensus/transaction.py +2 -2
- astreum/_consensus/workers/validation.py +5 -2
- astreum/_consensus/workers/verify.py +1 -1
- astreum/_node.py +49 -5
- astreum/_storage/patricia.py +2 -2
- {astreum-0.2.42.dist-info → astreum-0.2.44.dist-info}/METADATA +1 -1
- {astreum-0.2.42.dist-info → astreum-0.2.44.dist-info}/RECORD +16 -16
- {astreum-0.2.42.dist-info → astreum-0.2.44.dist-info}/WHEEL +0 -0
- {astreum-0.2.42.dist-info → astreum-0.2.44.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.42.dist-info → astreum-0.2.44.dist-info}/top_level.txt +0 -0
astreum/_communication/peer.py
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
|
|
2
|
+
from cryptography.hazmat.primitives import serialization
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from typing import Optional, Tuple
|
|
5
|
+
|
|
6
|
+
class Peer:
|
|
7
|
+
shared_key: bytes
|
|
8
|
+
timestamp: datetime
|
|
9
|
+
latest_block: bytes
|
|
10
|
+
address: Optional[Tuple[str, int]]
|
|
11
|
+
public_key: X25519PublicKey
|
|
12
|
+
public_key_bytes: bytes
|
|
13
|
+
|
|
14
|
+
def __init__(self, my_sec_key: X25519PrivateKey, peer_pub_key: X25519PublicKey):
|
|
15
|
+
self.shared_key = my_sec_key.exchange(peer_pub_key)
|
|
16
|
+
self.timestamp = datetime.now(timezone.utc)
|
|
17
|
+
self.latest_block = b""
|
|
18
|
+
self.address = None
|
|
19
|
+
self.public_key = peer_pub_key
|
|
20
|
+
self.public_key_bytes = peer_pub_key.public_bytes(
|
|
21
|
+
encoding=serialization.Encoding.Raw,
|
|
22
|
+
format=serialization.PublicFormat.Raw,
|
|
23
|
+
)
|
astreum/_communication/route.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
from typing import Dict, List, Union
|
|
1
|
+
from typing import Dict, List, Optional, Union
|
|
2
2
|
from cryptography.hazmat.primitives import serialization
|
|
3
3
|
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PublicKey
|
|
4
|
+
from .peer import Peer
|
|
4
5
|
|
|
5
6
|
PeerKey = Union[X25519PublicKey, bytes, bytearray]
|
|
6
7
|
|
|
@@ -15,7 +16,7 @@ class Route:
|
|
|
15
16
|
self.buckets: Dict[int, List[bytes]] = {
|
|
16
17
|
i: [] for i in range(len(self.relay_public_key_bytes) * 8)
|
|
17
18
|
}
|
|
18
|
-
self.peers = {}
|
|
19
|
+
self.peers: Dict[bytes, Peer] = {}
|
|
19
20
|
|
|
20
21
|
@staticmethod
|
|
21
22
|
def _matching_leading_bits(a: bytes, b: bytes) -> int:
|
|
@@ -38,13 +39,21 @@ class Route:
|
|
|
38
39
|
return key_bytes
|
|
39
40
|
raise TypeError("peer_public_key must be raw bytes or X25519PublicKey")
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
@staticmethod
|
|
43
|
+
def _xor_distance(a: bytes, b: bytes) -> int:
|
|
44
|
+
if len(a) != len(b):
|
|
45
|
+
raise ValueError("xor distance requires equal-length operands")
|
|
46
|
+
return int.from_bytes(bytes(x ^ y for x, y in zip(a, b)), "big", signed=False)
|
|
47
|
+
|
|
48
|
+
def add_peer(self, peer_public_key: PeerKey, peer: Optional[Peer] = None):
|
|
42
49
|
peer_public_key_bytes = self._normalize_peer_key(peer_public_key)
|
|
43
50
|
bucket_idx = self._matching_leading_bits(self.relay_public_key_bytes, peer_public_key_bytes)
|
|
44
51
|
if len(self.buckets[bucket_idx]) < self.bucket_size:
|
|
45
52
|
bucket = self.buckets[bucket_idx]
|
|
46
53
|
if peer_public_key_bytes not in bucket:
|
|
47
54
|
bucket.append(peer_public_key_bytes)
|
|
55
|
+
if peer is not None:
|
|
56
|
+
self.peers[peer_public_key_bytes] = peer
|
|
48
57
|
|
|
49
58
|
def remove_peer(self, peer_public_key: PeerKey):
|
|
50
59
|
peer_public_key_bytes = self._normalize_peer_key(peer_public_key)
|
|
@@ -56,3 +65,31 @@ class Route:
|
|
|
56
65
|
bucket.remove(peer_public_key_bytes)
|
|
57
66
|
except ValueError:
|
|
58
67
|
pass
|
|
68
|
+
self.peers.pop(peer_public_key_bytes, None)
|
|
69
|
+
|
|
70
|
+
def closest_peer_for_hash(self, target_hash: bytes) -> Optional[Peer]:
|
|
71
|
+
"""Return the peer with the minimal XOR distance to ``target_hash``."""
|
|
72
|
+
if not isinstance(target_hash, (bytes, bytearray)):
|
|
73
|
+
raise TypeError("target_hash must be bytes-like")
|
|
74
|
+
|
|
75
|
+
target = bytes(target_hash)
|
|
76
|
+
if len(target) != len(self.relay_public_key_bytes):
|
|
77
|
+
raise ValueError("target_hash must match peer key length (32 bytes)")
|
|
78
|
+
|
|
79
|
+
closest_key: Optional[bytes] = None
|
|
80
|
+
closest_distance: Optional[int] = None
|
|
81
|
+
|
|
82
|
+
for bucket in self.buckets.values():
|
|
83
|
+
for peer_key in bucket:
|
|
84
|
+
try:
|
|
85
|
+
distance = self._xor_distance(target, peer_key)
|
|
86
|
+
except ValueError:
|
|
87
|
+
continue
|
|
88
|
+
if closest_distance is None or distance < closest_distance:
|
|
89
|
+
closest_distance = distance
|
|
90
|
+
closest_key = peer_key
|
|
91
|
+
|
|
92
|
+
if closest_key is None:
|
|
93
|
+
return None
|
|
94
|
+
peer = self.peers.get(closest_key)
|
|
95
|
+
return peer
|
astreum/_communication/setup.py
CHANGED
|
@@ -95,9 +95,10 @@ def process_incoming_messages(node: "Node") -> None:
|
|
|
95
95
|
peer = Peer(node.relay_secret_key, sender_key)
|
|
96
96
|
except Exception:
|
|
97
97
|
continue
|
|
98
|
-
|
|
98
|
+
peer.address = address_key
|
|
99
|
+
|
|
99
100
|
node.peers[sender_public_key_bytes] = peer
|
|
100
|
-
node.peer_route.add_peer(sender_public_key_bytes)
|
|
101
|
+
node.peer_route.add_peer(sender_public_key_bytes, peer)
|
|
101
102
|
|
|
102
103
|
response = Message(handshake=True, sender=node.relay_public_key)
|
|
103
104
|
node.outgoing_queue.put((response.to_bytes(), address_key))
|
|
@@ -105,17 +106,25 @@ def process_incoming_messages(node: "Node") -> None:
|
|
|
105
106
|
|
|
106
107
|
elif old_key_bytes == sender_public_key_bytes:
|
|
107
108
|
# existing mapping with same key -> nothing to change
|
|
108
|
-
|
|
109
|
+
peer = node.peers.get(sender_public_key_bytes)
|
|
110
|
+
if peer is not None:
|
|
111
|
+
peer.address = address_key
|
|
109
112
|
|
|
110
113
|
else:
|
|
111
114
|
# address reused with a different key -> replace peer
|
|
112
115
|
node.peers.pop(old_key_bytes, None)
|
|
116
|
+
try:
|
|
117
|
+
node.peer_route.remove_peer(old_key_bytes)
|
|
118
|
+
except Exception:
|
|
119
|
+
pass
|
|
113
120
|
try:
|
|
114
121
|
peer = Peer(node.relay_secret_key, sender_key)
|
|
115
122
|
except Exception:
|
|
116
123
|
continue
|
|
117
|
-
|
|
124
|
+
peer.address = address_key
|
|
125
|
+
|
|
118
126
|
node.peers[sender_public_key_bytes] = peer
|
|
127
|
+
node.peer_route.add_peer(sender_public_key_bytes, peer)
|
|
119
128
|
|
|
120
129
|
match message.topic:
|
|
121
130
|
case MessageTopic.PING:
|
|
@@ -164,6 +173,65 @@ def process_incoming_messages(node: "Node") -> None:
|
|
|
164
173
|
if node.validation_secret_key is None:
|
|
165
174
|
continue
|
|
166
175
|
node._validation_transaction_queue.put(message.content)
|
|
176
|
+
|
|
177
|
+
case MessageTopic.STORAGE_REQUEST:
|
|
178
|
+
payload = message.content
|
|
179
|
+
if len(payload) < 32:
|
|
180
|
+
continue
|
|
181
|
+
|
|
182
|
+
atom_id = payload[:32]
|
|
183
|
+
provider_bytes = payload[32:]
|
|
184
|
+
if not provider_bytes:
|
|
185
|
+
continue
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
provider_str = provider_bytes.decode("utf-8")
|
|
189
|
+
except UnicodeDecodeError:
|
|
190
|
+
continue
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
host, port = addr[0], int(addr[1])
|
|
194
|
+
except Exception:
|
|
195
|
+
continue
|
|
196
|
+
address_key = (host, port)
|
|
197
|
+
sender_key_bytes = node.addresses.get(address_key)
|
|
198
|
+
if sender_key_bytes is None:
|
|
199
|
+
continue
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
local_key_bytes = node.relay_public_key.public_bytes(
|
|
203
|
+
encoding=serialization.Encoding.Raw,
|
|
204
|
+
format=serialization.PublicFormat.Raw,
|
|
205
|
+
)
|
|
206
|
+
except Exception:
|
|
207
|
+
continue
|
|
208
|
+
|
|
209
|
+
def xor_distance(target: bytes, key: bytes) -> int:
|
|
210
|
+
return int.from_bytes(
|
|
211
|
+
bytes(a ^ b for a, b in zip(target, key)),
|
|
212
|
+
byteorder="big",
|
|
213
|
+
signed=False,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
self_distance = xor_distance(atom_id, local_key_bytes)
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
closest_peer = node.peer_route.closest_peer_for_hash(atom_id)
|
|
220
|
+
except Exception:
|
|
221
|
+
closest_peer = None
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
closest_peer is not None
|
|
225
|
+
and closest_peer.public_key_bytes != sender_key_bytes
|
|
226
|
+
):
|
|
227
|
+
closest_distance = xor_distance(atom_id, closest_peer.public_key_bytes)
|
|
228
|
+
if closest_distance < self_distance:
|
|
229
|
+
target_addr = closest_peer.address
|
|
230
|
+
if target_addr is not None and target_addr != addr:
|
|
231
|
+
node.outgoing_queue.put((message.to_bytes(), target_addr))
|
|
232
|
+
continue
|
|
233
|
+
|
|
234
|
+
node.storage_index[atom_id] = provider_str.strip()
|
|
167
235
|
|
|
168
236
|
case _:
|
|
169
237
|
continue
|
astreum/_consensus/account.py
CHANGED
|
@@ -33,7 +33,7 @@ class Account:
|
|
|
33
33
|
|
|
34
34
|
@classmethod
|
|
35
35
|
def from_atom(cls, node: Any, account_id: bytes) -> "Account":
|
|
36
|
-
storage_get = node.
|
|
36
|
+
storage_get = node.storage_get
|
|
37
37
|
|
|
38
38
|
type_atom = storage_get(account_id)
|
|
39
39
|
if type_atom is None or type_atom.data != b"account":
|
astreum/_consensus/block.py
CHANGED
|
@@ -186,9 +186,9 @@ class Block:
|
|
|
186
186
|
if callable(source):
|
|
187
187
|
storage_get = source
|
|
188
188
|
else:
|
|
189
|
-
storage_get =
|
|
189
|
+
storage_get = source.storage_get
|
|
190
190
|
if not callable(storage_get):
|
|
191
|
-
raise TypeError("Block.from_atom requires a node with '
|
|
191
|
+
raise TypeError("Block.from_atom requires a node with 'storage_get' or a callable storage getter")
|
|
192
192
|
# 1) Expect main list
|
|
193
193
|
main_typ = storage_get(block_id)
|
|
194
194
|
if main_typ is None or main_typ.data != b"list":
|
|
@@ -76,7 +76,7 @@ class Transaction:
|
|
|
76
76
|
node: Any,
|
|
77
77
|
transaction_id: bytes,
|
|
78
78
|
) -> Transaction:
|
|
79
|
-
storage_get = node.
|
|
79
|
+
storage_get = node.storage_get
|
|
80
80
|
if not callable(storage_get):
|
|
81
81
|
raise NotImplementedError("node does not expose a storage getter")
|
|
82
82
|
|
|
@@ -204,7 +204,7 @@ def apply_transaction(node: Any, block: object, transaction_hash: bytes) -> None
|
|
|
204
204
|
|
|
205
205
|
block.accounts.set_account(address=recipient_account)
|
|
206
206
|
|
|
207
|
-
block.transactions.append(
|
|
207
|
+
block.transactions.append(transaction_hash)
|
|
208
208
|
|
|
209
209
|
receipt = Receipt(
|
|
210
210
|
transaction_hash=bytes(transaction_hash),
|
|
@@ -88,7 +88,7 @@ def make_validation_worker(
|
|
|
88
88
|
new_block.timestamp = max(int(now), min_allowed)
|
|
89
89
|
|
|
90
90
|
# atomize block
|
|
91
|
-
new_block_hash,
|
|
91
|
+
new_block_hash, new_block_atoms = new_block.to_atom()
|
|
92
92
|
# put as own latest block hash
|
|
93
93
|
node.latest_block_hash = new_block_hash
|
|
94
94
|
|
|
@@ -117,6 +117,9 @@ def make_validation_worker(
|
|
|
117
117
|
except Exception:
|
|
118
118
|
pass
|
|
119
119
|
|
|
120
|
-
#
|
|
120
|
+
# upload block atoms
|
|
121
|
+
|
|
122
|
+
# upload receipt atoms
|
|
123
|
+
# upload account atoms
|
|
121
124
|
|
|
122
125
|
return _validation_worker
|
|
@@ -17,7 +17,7 @@ def _process_peers_latest_block(
|
|
|
17
17
|
fk.head for fk in node.forks.values() if fk.head != latest_block_hash
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
new_fork.validate(storage_get=node.
|
|
20
|
+
new_fork.validate(storage_get=node.storage_get, stop_heads=current_fork_heads)
|
|
21
21
|
|
|
22
22
|
if new_fork.validated_upto and new_fork.validated_upto in node.forks:
|
|
23
23
|
ref = node.forks[new_fork.validated_upto]
|
astreum/_node.py
CHANGED
|
@@ -13,8 +13,9 @@ def bytes_touched(*vals: bytes) -> int:
|
|
|
13
13
|
class Node:
|
|
14
14
|
def __init__(self, config: dict):
|
|
15
15
|
# Storage Setup
|
|
16
|
-
self.in_memory_storage: Dict[bytes, Atom] = {}
|
|
17
|
-
self.in_memory_storage_lock = threading.RLock()
|
|
16
|
+
self.in_memory_storage: Dict[bytes, Atom] = {}
|
|
17
|
+
self.in_memory_storage_lock = threading.RLock()
|
|
18
|
+
self.storage_index: Dict[bytes, str] = {}
|
|
18
19
|
# Lispeum Setup
|
|
19
20
|
self.environments: Dict[uuid.UUID, Env] = {}
|
|
20
21
|
self.machine_environments_lock = threading.RLock()
|
|
@@ -25,9 +26,9 @@ class Node:
|
|
|
25
26
|
communication_setup(node=self, config=config)
|
|
26
27
|
except Exception:
|
|
27
28
|
pass
|
|
28
|
-
try:
|
|
29
|
-
from astreum._consensus import consensus_setup # type: ignore
|
|
30
|
-
consensus_setup(node=self)
|
|
29
|
+
try:
|
|
30
|
+
from astreum._consensus import consensus_setup # type: ignore
|
|
31
|
+
consensus_setup(node=self)
|
|
31
32
|
except Exception:
|
|
32
33
|
pass
|
|
33
34
|
|
|
@@ -56,3 +57,46 @@ class Node:
|
|
|
56
57
|
def _local_set(self, key: bytes, value: Atom) -> None:
|
|
57
58
|
with self.in_memory_storage_lock:
|
|
58
59
|
self.in_memory_storage[key] = value
|
|
60
|
+
|
|
61
|
+
def _network_get(self, key: bytes) -> Optional[Atom]:
|
|
62
|
+
# locate storage provider
|
|
63
|
+
# query storage provider
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
def storage_get(self, key: bytes) -> Optional[Atom]:
|
|
67
|
+
"""Retrieve an Atom by checking local storage first, then the network."""
|
|
68
|
+
atom = self._local_get(key)
|
|
69
|
+
if atom is not None:
|
|
70
|
+
return atom
|
|
71
|
+
return self._network_get(key)
|
|
72
|
+
|
|
73
|
+
def _network_set(self, atom: Atom) -> None:
|
|
74
|
+
"""Advertise an atom to the closest known peer so they can fetch it from us."""
|
|
75
|
+
try:
|
|
76
|
+
from src.astreum._communication.message import Message, MessageTopic
|
|
77
|
+
except Exception:
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
atom_id = atom.object_id()
|
|
81
|
+
try:
|
|
82
|
+
closest_peer = self.peer_route.closest_peer_for_hash(atom_id)
|
|
83
|
+
except Exception:
|
|
84
|
+
return
|
|
85
|
+
if closest_peer is None or closest_peer.address is None:
|
|
86
|
+
return
|
|
87
|
+
target_addr = closest_peer.address
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
provider_ip, provider_port = self.incoming_socket.getsockname()[:2]
|
|
91
|
+
except Exception:
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
provider_str = f"{provider_ip}:{int(provider_port)}"
|
|
95
|
+
try:
|
|
96
|
+
provider_bytes = provider_str.encode("utf-8")
|
|
97
|
+
except Exception:
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
payload = atom_id + provider_bytes
|
|
101
|
+
message = Message(topic=MessageTopic.STORAGE_REQUEST, content=payload)
|
|
102
|
+
self.outgoing_queue.put((message.to_bytes(), target_addr))
|
astreum/_storage/patricia.py
CHANGED
|
@@ -87,7 +87,7 @@ class PatriciaNode:
|
|
|
87
87
|
hops = 0
|
|
88
88
|
|
|
89
89
|
while current != ZERO32 and hops < 4:
|
|
90
|
-
atom = node.
|
|
90
|
+
atom = node.storage_get(current)
|
|
91
91
|
if atom is None:
|
|
92
92
|
raise ValueError("missing atom while decoding Patricia node")
|
|
93
93
|
entries.append(atom.data)
|
|
@@ -163,7 +163,7 @@ class PatriciaTrie:
|
|
|
163
163
|
if cached is not None:
|
|
164
164
|
return cached
|
|
165
165
|
|
|
166
|
-
if storage_node.
|
|
166
|
+
if storage_node.storage_get(h) is None:
|
|
167
167
|
return None
|
|
168
168
|
|
|
169
169
|
pat_node = PatriciaNode.from_atoms(storage_node, h)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.44
|
|
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,28 +1,28 @@
|
|
|
1
1
|
astreum/__init__.py,sha256=9tzA27B_eG5wRF1SAWJIV7xTmCcR1QFc123b_cvFOa4,345
|
|
2
|
-
astreum/_node.py,sha256=
|
|
2
|
+
astreum/_node.py,sha256=AUpLjqbHno-Oh2X47nEfoU4I9i_Aj5vjXM1mHQH0gfM,3780
|
|
3
3
|
astreum/format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
|
|
4
4
|
astreum/node.py,sha256=MmlK3jaANTMB3ZAxR8IaSc82OS9meJmVawYIVURADbg,39689
|
|
5
5
|
astreum/_communication/__init__.py,sha256=XJui0yOcfAur4HKt-8sSRlwB-MSU1rchkuOAY-nKDOE,207
|
|
6
|
-
astreum/_communication/message.py,sha256=
|
|
7
|
-
astreum/_communication/peer.py,sha256=
|
|
6
|
+
astreum/_communication/message.py,sha256=Wl1IITj7eY9_q0IOT4J7c5gsjS1bF51CH7GcSSuu5OM,3327
|
|
7
|
+
astreum/_communication/peer.py,sha256=CbqkyCwhFCiC2spd1-KjNdeVGNjjt2ECVs8uHot-ETI,875
|
|
8
8
|
astreum/_communication/ping.py,sha256=u_DQTZJsbMdYiDDqjdZDsLaN5na2m9WZjVeEM3zq9_Y,955
|
|
9
|
-
astreum/_communication/route.py,sha256=
|
|
10
|
-
astreum/_communication/setup.py,sha256=
|
|
9
|
+
astreum/_communication/route.py,sha256=Dqw8utefBeesZ311Nyizb7PO-g5dl26AoIUavttojHA,4037
|
|
10
|
+
astreum/_communication/setup.py,sha256=EN2GyVfGlVtkSHMhZWwJN33y-Ycfdvq9tjr38Myrmqg,11739
|
|
11
11
|
astreum/_communication/util.py,sha256=bJ3td3naDzmCelAJQpLwiDMoRBkijQl9YLROjsWyOrI,1256
|
|
12
12
|
astreum/_consensus/__init__.py,sha256=gOCpvnIeO17CGjUGr0odaKNvGEggmDRXfT5IuyrYtcM,376
|
|
13
|
-
astreum/_consensus/account.py,sha256=
|
|
13
|
+
astreum/_consensus/account.py,sha256=ClMB1e07ky5Wf7BwR4yhEjTSaWK2wiCmpvzio9AsZAY,3295
|
|
14
14
|
astreum/_consensus/accounts.py,sha256=zGq2BCMJPtD_lzcj4jqMzB2Foc3ptxXSPhc9zypB1T0,1106
|
|
15
|
-
astreum/_consensus/block.py,sha256=
|
|
15
|
+
astreum/_consensus/block.py,sha256=HybdVcV1D9f1wUE9XeFRnCGF9HH8YI1bgo-y1h-RS5o,12342
|
|
16
16
|
astreum/_consensus/chain.py,sha256=WwUeLrdg7uj--ZsUxse6xFlzO2QeQQggyKSL49KhfU0,2768
|
|
17
17
|
astreum/_consensus/fork.py,sha256=dK5DtT9hWCj_rQs6MS1c1bcGBbkgVTBPIOudYbqS9vw,3825
|
|
18
18
|
astreum/_consensus/genesis.py,sha256=oED7AHw0fPJgMu0OmhbbikJcbItw_bxVBVU8RlB2rJM,4766
|
|
19
19
|
astreum/_consensus/receipt.py,sha256=GPLspqVJHnyBr1cKmBoClsJyeEUecYmg3_acz4L4rRo,6031
|
|
20
20
|
astreum/_consensus/setup.py,sha256=agwqfOemdLqE0Z1zrPV2XHVmZ9sAxp8Bh4k6e2u-t8w,2385
|
|
21
|
-
astreum/_consensus/transaction.py,sha256=
|
|
21
|
+
astreum/_consensus/transaction.py,sha256=q9r0nQzB_67dV-9cIThCzpiJkTojP--8QENPOKxN5yw,7481
|
|
22
22
|
astreum/_consensus/workers/__init__.py,sha256=bS5FjbevbIR5FHbVGnT4Jli17VIld_5auemRw4CaHFU,278
|
|
23
23
|
astreum/_consensus/workers/discovery.py,sha256=X1yjKGjLSApMJ9mgWbnc7N21ALD09khDf-in-M45Mis,1683
|
|
24
|
-
astreum/_consensus/workers/validation.py,sha256=
|
|
25
|
-
astreum/_consensus/workers/verify.py,sha256=
|
|
24
|
+
astreum/_consensus/workers/validation.py,sha256=ftlwTDocwrvCk_BAicrOJgm3deZHgwjN_gn5r-gWE_0,4900
|
|
25
|
+
astreum/_consensus/workers/verify.py,sha256=wNkfh5qMARew79B-yyGL2UiExaSoGpOIq0fXUkDzpdw,1925
|
|
26
26
|
astreum/_lispeum/__init__.py,sha256=LAy2Z-gBBQlByBHRGUKaaQrOB7QzFEEyGRtInmwTpfU,304
|
|
27
27
|
astreum/_lispeum/environment.py,sha256=pJ0rjp9GoQxHhDiPIVei0jP7dZ_Pznso2O_tpp94-Ik,328
|
|
28
28
|
astreum/_lispeum/expression.py,sha256=io8tbCer_1TJee77yRbcNI5q-DPFGa8xZiC80tGvRRQ,1063
|
|
@@ -33,7 +33,7 @@ astreum/_lispeum/parser.py,sha256=WOW3sSZWkIzPEy3fYTyl0lrtkMxHL9zRrNSYztPDemQ,22
|
|
|
33
33
|
astreum/_lispeum/tokenizer.py,sha256=P68uIj4aPKzjuCJ85jfzRi67QztpuXIOC1vvLQueBI4,552
|
|
34
34
|
astreum/_storage/__init__.py,sha256=EmKZNAZmo3UVE3ekOOuckwFnBVjpa0Sy8Oxg72Lgdxc,53
|
|
35
35
|
astreum/_storage/atom.py,sha256=YFjvfMhniInch13iaKGpw4CCxxgyWonniryb-Rfse4A,4177
|
|
36
|
-
astreum/_storage/patricia.py,sha256=
|
|
36
|
+
astreum/_storage/patricia.py,sha256=7kvhW8RJWZ_EOHjNgEHue2E60FeQfJaKWtLIbM-6G2E,14853
|
|
37
37
|
astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
38
|
astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
|
|
39
39
|
astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
|
|
@@ -47,8 +47,8 @@ astreum/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
47
47
|
astreum/storage/object.py,sha256=knFlvw_tpcC4twSu1DGNpHX31wlANN8E5dgEqIfU--Q,2041
|
|
48
48
|
astreum/storage/setup.py,sha256=1-9ztEFI_BvRDvAA0lAn4mFya8iq65THTArlj--M3Hg,626
|
|
49
49
|
astreum/utils/integer.py,sha256=iQt-klWOYVghu_NOT341MmHbOle4FDT3by4PNKNXscg,736
|
|
50
|
-
astreum-0.2.
|
|
51
|
-
astreum-0.2.
|
|
52
|
-
astreum-0.2.
|
|
53
|
-
astreum-0.2.
|
|
54
|
-
astreum-0.2.
|
|
50
|
+
astreum-0.2.44.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
51
|
+
astreum-0.2.44.dist-info/METADATA,sha256=BfQ0S0XtFjxl4evYAAWk9buUhQAVAq7L37patJVYDDU,6181
|
|
52
|
+
astreum-0.2.44.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
53
|
+
astreum-0.2.44.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
54
|
+
astreum-0.2.44.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|