astreum 0.2.44__py3-none-any.whl → 0.2.46__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/_consensus/genesis.py +12 -81
- astreum/_consensus/setup.py +50 -3
- astreum/_lispeum/parser.py +25 -25
- astreum/_node.py +28 -26
- astreum/utils/bytes.py +24 -0
- {astreum-0.2.44.dist-info → astreum-0.2.46.dist-info}/METADATA +1 -1
- {astreum-0.2.44.dist-info → astreum-0.2.46.dist-info}/RECORD +10 -9
- {astreum-0.2.44.dist-info → astreum-0.2.46.dist-info}/WHEEL +0 -0
- {astreum-0.2.44.dist-info → astreum-0.2.46.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.44.dist-info → astreum-0.2.46.dist-info}/top_level.txt +0 -0
astreum/_consensus/genesis.py
CHANGED
|
@@ -1,77 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, List
|
|
5
5
|
|
|
6
6
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
7
7
|
|
|
8
8
|
from .account import Account
|
|
9
9
|
from .block import Block
|
|
10
|
-
from .._storage.atom import
|
|
11
|
-
from .._storage.patricia import PatriciaTrie
|
|
10
|
+
from .._storage.atom import ZERO32
|
|
11
|
+
from .._storage.patricia import PatriciaTrie
|
|
12
|
+
from ..utils.integer import int_to_bytes
|
|
12
13
|
|
|
13
14
|
TREASURY_ADDRESS = b"\x01" * 32
|
|
14
15
|
BURN_ADDRESS = b"\x00" * 32
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def _int_to_be_bytes(value: int) -> bytes:
|
|
18
|
-
if value < 0:
|
|
19
|
-
raise ValueError("integer fields in genesis must be non-negative")
|
|
20
|
-
if value == 0:
|
|
21
|
-
return b"\x00"
|
|
22
|
-
length = (value.bit_length() + 7) // 8
|
|
23
|
-
return value.to_bytes(length, "big")
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _make_list(child_ids: List[bytes]) -> Tuple[bytes, List[Atom]]:
|
|
27
|
-
next_hash = ZERO32
|
|
28
|
-
chain: List[Atom] = []
|
|
29
|
-
for child_id in reversed(child_ids):
|
|
30
|
-
elem = Atom.from_data(data=child_id, next_hash=next_hash)
|
|
31
|
-
next_hash = elem.object_id()
|
|
32
|
-
chain.append(elem)
|
|
33
|
-
chain.reverse()
|
|
34
|
-
|
|
35
|
-
value_atom = Atom.from_data(
|
|
36
|
-
data=len(child_ids).to_bytes(8, "little"),
|
|
37
|
-
next_hash=next_hash,
|
|
38
|
-
)
|
|
39
|
-
type_atom = Atom.from_data(data=b"list", next_hash=value_atom.object_id())
|
|
40
|
-
atoms = chain + [value_atom, type_atom]
|
|
41
|
-
return type_atom.object_id(), atoms
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _store_atoms(node: Any, atoms: Iterable[Atom]) -> None:
|
|
45
|
-
setter = getattr(node, "_local_set", None)
|
|
46
|
-
if not callable(setter):
|
|
47
|
-
raise TypeError("node must expose '_local_set(object_id, atom)'")
|
|
48
|
-
for atom in atoms:
|
|
49
|
-
setter(atom.object_id(), atom)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def _persist_trie(trie: PatriciaTrie, node: Any) -> None:
|
|
53
|
-
for patricia_node in trie.nodes.values():
|
|
54
|
-
_, atoms = patricia_node.to_atoms()
|
|
55
|
-
_store_atoms(node, atoms)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if not hasattr(PatriciaNode, "to_bytes"):
|
|
59
|
-
def _patricia_node_to_bytes(self: PatriciaNode) -> bytes: # type: ignore[no-redef]
|
|
60
|
-
fields = [
|
|
61
|
-
bytes([self.key_len]) + self.key,
|
|
62
|
-
self.child_0 or ZERO32,
|
|
63
|
-
self.child_1 or ZERO32,
|
|
64
|
-
self.value or b"",
|
|
65
|
-
]
|
|
66
|
-
encoded: List[bytes] = []
|
|
67
|
-
for field in fields:
|
|
68
|
-
encoded.append(len(field).to_bytes(4, "big"))
|
|
69
|
-
encoded.append(field)
|
|
70
|
-
return b"".join(encoded)
|
|
71
|
-
|
|
72
|
-
PatriciaNode.to_bytes = _patricia_node_to_bytes # type: ignore[attr-defined]
|
|
73
|
-
|
|
74
|
-
|
|
75
16
|
def create_genesis_block(node: Any, validator_public_key: bytes, validator_secret_key: bytes) -> Block:
|
|
76
17
|
validator_pk = bytes(validator_public_key)
|
|
77
18
|
|
|
@@ -80,30 +21,21 @@ def create_genesis_block(node: Any, validator_public_key: bytes, validator_secre
|
|
|
80
21
|
|
|
81
22
|
# 1. Stake trie with single validator stake of 1 (encoded on 32 bytes).
|
|
82
23
|
stake_trie = PatriciaTrie()
|
|
83
|
-
stake_amount = (1)
|
|
84
|
-
stake_trie.put(node, validator_pk, stake_amount)
|
|
85
|
-
|
|
86
|
-
stake_root = stake_trie.root_hash or ZERO32
|
|
24
|
+
stake_amount = int_to_bytes(1)
|
|
25
|
+
stake_trie.put(storage_node=node, key=validator_pk, value=stake_amount)
|
|
26
|
+
stake_root = stake_trie.root_hash
|
|
87
27
|
|
|
88
28
|
# 2. Account trie with treasury, burn, and validator accounts.
|
|
89
29
|
accounts_trie = PatriciaTrie()
|
|
90
30
|
|
|
91
31
|
treasury_account = Account.create(balance=1, data=stake_root, counter=0)
|
|
92
|
-
|
|
93
|
-
_store_atoms(node, treasury_atoms)
|
|
94
|
-
accounts_trie.put(node, TREASURY_ADDRESS, treasury_account_id)
|
|
32
|
+
accounts_trie.put(storage_node=node, key=TREASURY_ADDRESS, value=treasury_account.hash)
|
|
95
33
|
|
|
96
34
|
burn_account = Account.create(balance=0, data=b"", counter=0)
|
|
97
|
-
|
|
98
|
-
_store_atoms(node, burn_atoms)
|
|
99
|
-
accounts_trie.put(node, BURN_ADDRESS, burn_account_id)
|
|
35
|
+
accounts_trie.put(storage_node=node, key=BURN_ADDRESS, value=burn_account.hash)
|
|
100
36
|
|
|
101
37
|
validator_account = Account.create(balance=0, data=b"", counter=0)
|
|
102
|
-
|
|
103
|
-
_store_atoms(node, validator_atoms)
|
|
104
|
-
accounts_trie.put(node, validator_pk, validator_account_id)
|
|
105
|
-
|
|
106
|
-
_persist_trie(accounts_trie, node)
|
|
38
|
+
accounts_trie.put(storage_node=node, key=validator_pk, value=validator_account.hash)
|
|
107
39
|
|
|
108
40
|
accounts_root = accounts_trie.root_hash
|
|
109
41
|
if accounts_root is None:
|
|
@@ -134,8 +66,7 @@ def create_genesis_block(node: Any, validator_public_key: bytes, validator_secre
|
|
|
134
66
|
|
|
135
67
|
secret = Ed25519PrivateKey.from_private_bytes(validator_secret_key)
|
|
136
68
|
block.signature = secret.sign(block.body_hash)
|
|
137
|
-
block_hash,
|
|
138
|
-
_store_atoms(node, block_atoms)
|
|
69
|
+
block_hash, _ = block.to_atom()
|
|
139
70
|
|
|
140
71
|
block.hash = block_hash
|
|
141
72
|
return block
|
astreum/_consensus/setup.py
CHANGED
|
@@ -2,13 +2,15 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import threading
|
|
4
4
|
from queue import Queue
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any, Optional
|
|
6
6
|
|
|
7
7
|
from .workers import (
|
|
8
8
|
make_discovery_worker,
|
|
9
9
|
make_validation_worker,
|
|
10
10
|
make_verify_worker,
|
|
11
11
|
)
|
|
12
|
+
from .genesis import create_genesis_block
|
|
13
|
+
from ..utils.bytes import hex_to_bytes
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
def current_validator(node: Any) -> bytes:
|
|
@@ -16,7 +18,9 @@ def current_validator(node: Any) -> bytes:
|
|
|
16
18
|
raise NotImplementedError("current_validator must be implemented by the host node")
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
def consensus_setup(node: Any) -> None:
|
|
21
|
+
def consensus_setup(node: Any, config: Optional[dict] = None) -> None:
|
|
22
|
+
config = config or {}
|
|
23
|
+
|
|
20
24
|
# Shared state
|
|
21
25
|
node.validation_lock = getattr(node, "validation_lock", threading.RLock())
|
|
22
26
|
|
|
@@ -26,6 +30,12 @@ def consensus_setup(node: Any) -> None:
|
|
|
26
30
|
node.chains = getattr(node, "chains", {})
|
|
27
31
|
node.forks = getattr(node, "forks", {})
|
|
28
32
|
|
|
33
|
+
node.latest_block_hash = None
|
|
34
|
+
latest_block_hex = config.get("latest_block_hash")
|
|
35
|
+
if latest_block_hex is not None:
|
|
36
|
+
node.latest_block_hash = hex_to_bytes(latest_block_hex, expected_length=32)
|
|
37
|
+
node.latest_block = None
|
|
38
|
+
|
|
29
39
|
# Pending transactions queue (hash-only entries)
|
|
30
40
|
node._validation_transaction_queue = getattr(
|
|
31
41
|
node, "_validation_transaction_queue", Queue()
|
|
@@ -64,5 +74,42 @@ def consensus_setup(node: Any) -> None:
|
|
|
64
74
|
)
|
|
65
75
|
node.consensus_discovery_thread.start()
|
|
66
76
|
node.consensus_verify_thread.start()
|
|
67
|
-
|
|
77
|
+
|
|
78
|
+
validator_secret_hex = config.get("validation_secret_key")
|
|
79
|
+
if validator_secret_hex:
|
|
80
|
+
validator_secret_bytes = hex_to_bytes(validator_secret_hex, expected_length=32)
|
|
81
|
+
try:
|
|
82
|
+
from cryptography.hazmat.primitives import serialization
|
|
83
|
+
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
84
|
+
|
|
85
|
+
validator_private = ed25519.Ed25519PrivateKey.from_private_bytes(
|
|
86
|
+
validator_secret_bytes
|
|
87
|
+
)
|
|
88
|
+
except Exception as exc:
|
|
89
|
+
raise ValueError("invalid validation_secret_key") from exc
|
|
90
|
+
|
|
91
|
+
validator_public_bytes = validator_private.public_key().public_bytes(
|
|
92
|
+
encoding=serialization.Encoding.Raw,
|
|
93
|
+
format=serialization.PublicFormat.Raw,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
node.validation_secret_key = validator_private
|
|
97
|
+
node.validation_public_key = validator_public_bytes
|
|
98
|
+
|
|
99
|
+
if node.latest_block_hash is None:
|
|
100
|
+
genesis_block = create_genesis_block(
|
|
101
|
+
node,
|
|
102
|
+
validator_public_key=validator_public_bytes,
|
|
103
|
+
validator_secret_key=validator_secret_bytes,
|
|
104
|
+
)
|
|
105
|
+
genesis_hash, genesis_atoms = genesis_block.to_atom()
|
|
106
|
+
if hasattr(node, "_local_set"):
|
|
107
|
+
for atom in genesis_atoms:
|
|
108
|
+
try:
|
|
109
|
+
node._local_set(atom.object_id(), atom)
|
|
110
|
+
except Exception:
|
|
111
|
+
pass
|
|
112
|
+
node.latest_block_hash = genesis_hash
|
|
113
|
+
node.latest_block = genesis_block
|
|
114
|
+
|
|
68
115
|
node.consensus_validation_thread.start()
|
astreum/_lispeum/parser.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from typing import List, Tuple
|
|
2
|
-
from
|
|
1
|
+
from typing import List, Tuple
|
|
2
|
+
from . import Expr
|
|
3
3
|
|
|
4
4
|
class ParseError(Exception):
|
|
5
5
|
pass
|
|
@@ -27,30 +27,30 @@ def _parse_one(tokens: List[str], pos: int = 0) -> Tuple[Expr, int]:
|
|
|
27
27
|
if tok == ')':
|
|
28
28
|
raise ParseError("unexpected ')'")
|
|
29
29
|
|
|
30
|
-
# try integer → Bytes (variable-length two's complement)
|
|
31
|
-
try:
|
|
32
|
-
n = int(tok)
|
|
33
|
-
# encode as minimal-width signed two's complement, big-endian
|
|
34
|
-
def int_to_min_tc(v: int) -> bytes:
|
|
35
|
-
"""Return the minimal-width signed two's complement big-endian
|
|
36
|
-
byte encoding of integer v. Width expands just enough so that
|
|
37
|
-
decoding with signed=True yields the same value and sign.
|
|
38
|
-
Example: 0 -> b"\x00", 127 -> b"\x7f", 128 -> b"\x00\x80".
|
|
39
|
-
"""
|
|
40
|
-
if v == 0:
|
|
41
|
-
return b"\x00"
|
|
42
|
-
w = 1
|
|
43
|
-
while True:
|
|
44
|
-
try:
|
|
45
|
-
return v.to_bytes(w, "big", signed=True)
|
|
46
|
-
except OverflowError:
|
|
47
|
-
w += 1
|
|
48
|
-
|
|
49
|
-
return Expr.Bytes(int_to_min_tc(n)), pos + 1
|
|
50
|
-
except ValueError:
|
|
51
|
-
return Expr.Symbol(tok), pos + 1
|
|
30
|
+
# try integer → Bytes (variable-length two's complement)
|
|
31
|
+
try:
|
|
32
|
+
n = int(tok)
|
|
33
|
+
# encode as minimal-width signed two's complement, big-endian
|
|
34
|
+
def int_to_min_tc(v: int) -> bytes:
|
|
35
|
+
"""Return the minimal-width signed two's complement big-endian
|
|
36
|
+
byte encoding of integer v. Width expands just enough so that
|
|
37
|
+
decoding with signed=True yields the same value and sign.
|
|
38
|
+
Example: 0 -> b"\x00", 127 -> b"\x7f", 128 -> b"\x00\x80".
|
|
39
|
+
"""
|
|
40
|
+
if v == 0:
|
|
41
|
+
return b"\x00"
|
|
42
|
+
w = 1
|
|
43
|
+
while True:
|
|
44
|
+
try:
|
|
45
|
+
return v.to_bytes(w, "big", signed=True)
|
|
46
|
+
except OverflowError:
|
|
47
|
+
w += 1
|
|
48
|
+
|
|
49
|
+
return Expr.Bytes(int_to_min_tc(n)), pos + 1
|
|
50
|
+
except ValueError:
|
|
51
|
+
return Expr.Symbol(tok), pos + 1
|
|
52
52
|
|
|
53
53
|
def parse(tokens: List[str]) -> Tuple[Expr, List[str]]:
|
|
54
54
|
"""Parse tokens into an Expr and return (expr, remaining_tokens)."""
|
|
55
55
|
expr, next_pos = _parse_one(tokens, 0)
|
|
56
|
-
return expr, tokens[next_pos:]
|
|
56
|
+
return expr, tokens[next_pos:]
|
astreum/_node.py
CHANGED
|
@@ -3,8 +3,8 @@ from typing import Dict, Optional
|
|
|
3
3
|
import uuid
|
|
4
4
|
import threading
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
from
|
|
6
|
+
from ._storage.atom import Atom
|
|
7
|
+
from ._lispeum import Env, Expr, low_eval, parse, tokenize, ParseError
|
|
8
8
|
|
|
9
9
|
def bytes_touched(*vals: bytes) -> int:
|
|
10
10
|
"""For metering: how many bytes were manipulated (max of operands)."""
|
|
@@ -13,9 +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()
|
|
18
|
-
self.storage_index: Dict[bytes, str] = {}
|
|
16
|
+
self.in_memory_storage: Dict[bytes, Atom] = {}
|
|
17
|
+
self.in_memory_storage_lock = threading.RLock()
|
|
18
|
+
self.storage_index: Dict[bytes, str] = {}
|
|
19
19
|
# Lispeum Setup
|
|
20
20
|
self.environments: Dict[uuid.UUID, Env] = {}
|
|
21
21
|
self.machine_environments_lock = threading.RLock()
|
|
@@ -28,9 +28,11 @@ class Node:
|
|
|
28
28
|
pass
|
|
29
29
|
try:
|
|
30
30
|
from astreum._consensus import consensus_setup # type: ignore
|
|
31
|
-
consensus_setup(node=self)
|
|
31
|
+
consensus_setup(node=self, config=config)
|
|
32
32
|
except Exception:
|
|
33
33
|
pass
|
|
34
|
+
|
|
35
|
+
|
|
34
36
|
|
|
35
37
|
# ---- Env helpers ----
|
|
36
38
|
def env_get(self, env_id: uuid.UUID, key: bytes) -> Optional[Expr]:
|
|
@@ -73,30 +75,30 @@ class Node:
|
|
|
73
75
|
def _network_set(self, atom: Atom) -> None:
|
|
74
76
|
"""Advertise an atom to the closest known peer so they can fetch it from us."""
|
|
75
77
|
try:
|
|
76
|
-
from
|
|
78
|
+
from ._communication.message import Message, MessageTopic
|
|
77
79
|
except Exception:
|
|
78
80
|
return
|
|
79
81
|
|
|
80
82
|
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
|
|
83
|
+
try:
|
|
84
|
+
closest_peer = self.peer_route.closest_peer_for_hash(atom_id)
|
|
85
|
+
except Exception:
|
|
86
|
+
return
|
|
87
|
+
if closest_peer is None or closest_peer.address is None:
|
|
88
|
+
return
|
|
89
|
+
target_addr = closest_peer.address
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
provider_ip, provider_port = self.incoming_socket.getsockname()[:2]
|
|
93
|
+
except Exception:
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
provider_str = f"{provider_ip}:{int(provider_port)}"
|
|
97
|
+
try:
|
|
98
|
+
provider_bytes = provider_str.encode("utf-8")
|
|
99
|
+
except Exception:
|
|
100
|
+
return
|
|
88
101
|
|
|
89
|
-
|
|
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
|
|
102
|
+
payload = atom_id + provider_bytes
|
|
101
103
|
message = Message(topic=MessageTopic.STORAGE_REQUEST, content=payload)
|
|
102
104
|
self.outgoing_queue.put((message.to_bytes(), target_addr))
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.46
|
|
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,5 +1,5 @@
|
|
|
1
1
|
astreum/__init__.py,sha256=9tzA27B_eG5wRF1SAWJIV7xTmCcR1QFc123b_cvFOa4,345
|
|
2
|
-
astreum/_node.py,sha256=
|
|
2
|
+
astreum/_node.py,sha256=dTwXjnCJZHjUw8dPmH7neaL1-M4rso77Aogo0935vsY,3796
|
|
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
|
|
@@ -15,9 +15,9 @@ astreum/_consensus/accounts.py,sha256=zGq2BCMJPtD_lzcj4jqMzB2Foc3ptxXSPhc9zypB1T
|
|
|
15
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
|
-
astreum/_consensus/genesis.py,sha256=
|
|
18
|
+
astreum/_consensus/genesis.py,sha256=YOzEEcpH5lQUdRNz1P8cfeddh-IJzjTbOiVKrEPHXPg,2506
|
|
19
19
|
astreum/_consensus/receipt.py,sha256=GPLspqVJHnyBr1cKmBoClsJyeEUecYmg3_acz4L4rRo,6031
|
|
20
|
-
astreum/_consensus/setup.py,sha256=
|
|
20
|
+
astreum/_consensus/setup.py,sha256=KHW2KzHRgCMLWaJNV2utosKdk7nxjI5aF9ie7jctgcU,4257
|
|
21
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
|
|
@@ -29,7 +29,7 @@ astreum/_lispeum/expression.py,sha256=io8tbCer_1TJee77yRbcNI5q-DPFGa8xZiC80tGvRR
|
|
|
29
29
|
astreum/_lispeum/high_evaluation.py,sha256=7MwIeVZMPumYvKXn6Lkn-GrZhRNB6MjnUUWdiYT7Ei0,7952
|
|
30
30
|
astreum/_lispeum/low_evaluation.py,sha256=HgyCSAmL5K5SKq3Xw_BtbTZZUJbMg4-bVZW-A12glQ0,4373
|
|
31
31
|
astreum/_lispeum/meter.py,sha256=5q2PFW7_jmgKVM1-vwE4RRjMfPEthUA4iu1CwR-Axws,505
|
|
32
|
-
astreum/_lispeum/parser.py,sha256=
|
|
32
|
+
astreum/_lispeum/parser.py,sha256=rpxznlILbGruCS8wS_SQajYs7MlNPoMPbQ48XEjLeRo,2277
|
|
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
|
|
@@ -46,9 +46,10 @@ astreum/models/patricia.py,sha256=ohmXrcaz7Ae561tyC4u4iPOkQPkKr8N0IWJek4upFIg,13
|
|
|
46
46
|
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
|
+
astreum/utils/bytes.py,sha256=9QTWC2JCdwWLB5R2mPtmjPro0IUzE58DL3uEul4AheE,846
|
|
49
50
|
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.
|
|
51
|
+
astreum-0.2.46.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
52
|
+
astreum-0.2.46.dist-info/METADATA,sha256=o454zFl45Clnos8EwXm0PCSivnHw8fkoOC3C2mCFXYo,6181
|
|
53
|
+
astreum-0.2.46.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
54
|
+
astreum-0.2.46.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
55
|
+
astreum-0.2.46.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|