astreum 0.2.29__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/__init__.py +9 -1
- astreum/_communication/__init__.py +11 -0
- astreum/{models → _communication}/message.py +101 -64
- astreum/_communication/peer.py +23 -0
- astreum/_communication/ping.py +33 -0
- astreum/_communication/route.py +95 -0
- astreum/_communication/setup.py +322 -0
- astreum/_communication/util.py +42 -0
- astreum/_consensus/__init__.py +20 -0
- astreum/_consensus/account.py +95 -0
- astreum/_consensus/accounts.py +38 -0
- astreum/_consensus/block.py +311 -0
- astreum/_consensus/chain.py +66 -0
- astreum/_consensus/fork.py +100 -0
- astreum/_consensus/genesis.py +72 -0
- astreum/_consensus/receipt.py +136 -0
- astreum/_consensus/setup.py +115 -0
- astreum/_consensus/transaction.py +215 -0
- astreum/_consensus/workers/__init__.py +9 -0
- astreum/_consensus/workers/discovery.py +48 -0
- astreum/_consensus/workers/validation.py +125 -0
- astreum/_consensus/workers/verify.py +63 -0
- astreum/_lispeum/__init__.py +16 -0
- astreum/_lispeum/environment.py +13 -0
- astreum/_lispeum/expression.py +190 -0
- astreum/_lispeum/high_evaluation.py +236 -0
- astreum/_lispeum/low_evaluation.py +123 -0
- astreum/_lispeum/meter.py +18 -0
- astreum/_lispeum/parser.py +51 -0
- astreum/_lispeum/tokenizer.py +22 -0
- astreum/_node.py +198 -0
- astreum/_storage/__init__.py +7 -0
- astreum/_storage/atom.py +109 -0
- astreum/_storage/patricia.py +478 -0
- astreum/_storage/setup.py +35 -0
- astreum/models/block.py +48 -39
- astreum/node.py +755 -563
- astreum/utils/bytes.py +24 -0
- astreum/utils/integer.py +25 -0
- astreum/utils/logging.py +219 -0
- {astreum-0.2.29.dist-info → astreum-0.2.61.dist-info}/METADATA +50 -14
- astreum-0.2.61.dist-info/RECORD +57 -0
- astreum/lispeum/__init__.py +0 -2
- astreum/lispeum/environment.py +0 -40
- astreum/lispeum/expression.py +0 -86
- astreum/lispeum/parser.py +0 -41
- astreum/lispeum/tokenizer.py +0 -52
- astreum/models/account.py +0 -91
- astreum/models/accounts.py +0 -34
- astreum/models/transaction.py +0 -106
- astreum/relay/__init__.py +0 -0
- astreum/relay/peer.py +0 -9
- astreum/relay/route.py +0 -25
- astreum/relay/setup.py +0 -58
- astreum-0.2.29.dist-info/RECORD +0 -33
- {astreum-0.2.29.dist-info → astreum-0.2.61.dist-info}/WHEEL +0 -0
- {astreum-0.2.29.dist-info → astreum-0.2.61.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.29.dist-info → astreum-0.2.61.dist-info}/top_level.txt +0 -0
astreum/models/account.py
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Optional, Callable
|
|
4
|
-
|
|
5
|
-
from .merkle import MerkleTree
|
|
6
|
-
|
|
7
|
-
_FIELD_ORDER = ["balance", "data", "nonce"]
|
|
8
|
-
_INT_FIELDS = {"balance", "nonce"}
|
|
9
|
-
|
|
10
|
-
def _int_to_min_bytes(i: int) -> bytes:
|
|
11
|
-
length = (i.bit_length() + 7) // 8 or 1
|
|
12
|
-
return i.to_bytes(length, "big")
|
|
13
|
-
|
|
14
|
-
class Account:
|
|
15
|
-
def __init__(
|
|
16
|
-
self,
|
|
17
|
-
body_hash: bytes,
|
|
18
|
-
*,
|
|
19
|
-
body_tree: Optional[MerkleTree] = None,
|
|
20
|
-
get_node_fn: Optional[Callable[[bytes], Optional[bytes]]] = None,
|
|
21
|
-
) -> None:
|
|
22
|
-
self._body_hash = body_hash
|
|
23
|
-
self._body_tree = body_tree
|
|
24
|
-
self._balance: Optional[int] = None
|
|
25
|
-
self._data: Optional[bytes] = None
|
|
26
|
-
self._nonce: Optional[int] = None
|
|
27
|
-
|
|
28
|
-
if self._body_tree and get_node_fn:
|
|
29
|
-
self._body_tree._node_get = get_node_fn
|
|
30
|
-
|
|
31
|
-
@classmethod
|
|
32
|
-
def create(
|
|
33
|
-
cls,
|
|
34
|
-
balance: int,
|
|
35
|
-
data: bytes,
|
|
36
|
-
nonce: int,
|
|
37
|
-
) -> Account:
|
|
38
|
-
"""Build an Account body from explicit fields in alphabetical order."""
|
|
39
|
-
# prepare values dict
|
|
40
|
-
values = {"balance": balance, "data": data, "nonce": nonce}
|
|
41
|
-
|
|
42
|
-
# build leaves in alphabetical order
|
|
43
|
-
leaves: list[bytes] = []
|
|
44
|
-
for name in _FIELD_ORDER:
|
|
45
|
-
v = values[name]
|
|
46
|
-
if name in _INT_FIELDS:
|
|
47
|
-
leaves.append(_int_to_min_bytes(v)) # type: ignore[arg-type]
|
|
48
|
-
else:
|
|
49
|
-
leaves.append(v)
|
|
50
|
-
|
|
51
|
-
tree = MerkleTree.from_leaves(leaves)
|
|
52
|
-
return cls(tree.root_hash, body_tree=tree)
|
|
53
|
-
|
|
54
|
-
def body_hash(self) -> bytes:
|
|
55
|
-
"""Return the Merkle root of the account body."""
|
|
56
|
-
return self._body_hash
|
|
57
|
-
|
|
58
|
-
def _require_tree(self) -> MerkleTree:
|
|
59
|
-
if not self._body_tree:
|
|
60
|
-
raise ValueError("Body tree unavailable for this Account")
|
|
61
|
-
return self._body_tree
|
|
62
|
-
|
|
63
|
-
def balance(self) -> int:
|
|
64
|
-
"""Fetch & cache the `balance` field (leaf 0)."""
|
|
65
|
-
if self._balance is not None:
|
|
66
|
-
return self._balance
|
|
67
|
-
raw = self._require_tree().get(0)
|
|
68
|
-
if raw is None:
|
|
69
|
-
raise ValueError("Merkle leaf 0 (balance) missing")
|
|
70
|
-
self._balance = int.from_bytes(raw, "big")
|
|
71
|
-
return self._balance
|
|
72
|
-
|
|
73
|
-
def data(self) -> bytes:
|
|
74
|
-
"""Fetch & cache the `data` field (leaf 1)."""
|
|
75
|
-
if self._data is not None:
|
|
76
|
-
return self._data
|
|
77
|
-
raw = self._require_tree().get(1)
|
|
78
|
-
if raw is None:
|
|
79
|
-
raise ValueError("Merkle leaf 1 (data) missing")
|
|
80
|
-
self._data = raw
|
|
81
|
-
return self._data
|
|
82
|
-
|
|
83
|
-
def nonce(self) -> int:
|
|
84
|
-
"""Fetch & cache the `nonce` field (leaf 2)."""
|
|
85
|
-
if self._nonce is not None:
|
|
86
|
-
return self._nonce
|
|
87
|
-
raw = self._require_tree().get(2)
|
|
88
|
-
if raw is None:
|
|
89
|
-
raise ValueError("Merkle leaf 2 (nonce) missing")
|
|
90
|
-
self._nonce = int.from_bytes(raw, "big")
|
|
91
|
-
return self._nonce
|
astreum/models/accounts.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from typing import Dict, Optional, Callable
|
|
3
|
-
from .patricia import PatriciaTrie
|
|
4
|
-
from .account import Account
|
|
5
|
-
|
|
6
|
-
class Accounts:
|
|
7
|
-
def __init__(
|
|
8
|
-
self,
|
|
9
|
-
root_hash: Optional[bytes] = None,
|
|
10
|
-
global_get_fn: Optional[Callable[[bytes], Optional[bytes]]] = None,
|
|
11
|
-
) -> None:
|
|
12
|
-
self._global_get_fn = global_get_fn
|
|
13
|
-
self._trie = PatriciaTrie(node_get=global_get_fn, root_hash=root_hash)
|
|
14
|
-
self._cache: Dict[bytes, Account] = {}
|
|
15
|
-
|
|
16
|
-
@property
|
|
17
|
-
def root_hash(self) -> Optional[bytes]:
|
|
18
|
-
return self._trie.root_hash
|
|
19
|
-
|
|
20
|
-
def get_account(self, address: bytes) -> Optional[Account]:
|
|
21
|
-
if address in self._cache:
|
|
22
|
-
return self._cache[address]
|
|
23
|
-
|
|
24
|
-
body_hash: Optional[bytes] = self._trie.get(address)
|
|
25
|
-
if body_hash is None:
|
|
26
|
-
return None
|
|
27
|
-
|
|
28
|
-
acc = Account(body_hash, get_node_fn=self._global_get_fn)
|
|
29
|
-
self._cache[address] = acc
|
|
30
|
-
return acc
|
|
31
|
-
|
|
32
|
-
def set_account(self, address: bytes, account: Account) -> None:
|
|
33
|
-
self._cache[address] = account
|
|
34
|
-
self._trie.put(address, account.body_hash())
|
astreum/models/transaction.py
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Dict, List, Optional, Union, Any, Callable
|
|
4
|
-
|
|
5
|
-
from .merkle import MerkleTree
|
|
6
|
-
from ..crypto import ed25519
|
|
7
|
-
|
|
8
|
-
_FIELD_ORDER: List[str] = [
|
|
9
|
-
"amount",
|
|
10
|
-
"balance",
|
|
11
|
-
"fee",
|
|
12
|
-
"nonce",
|
|
13
|
-
"recipient_pk",
|
|
14
|
-
"sender_pk",
|
|
15
|
-
]
|
|
16
|
-
|
|
17
|
-
_INT_FIELDS = {"amount", "balance", "fee", "nonce"}
|
|
18
|
-
|
|
19
|
-
def _int_to_min_bytes(i: int) -> bytes:
|
|
20
|
-
length = (i.bit_length() + 7) // 8 or 1
|
|
21
|
-
return i.to_bytes(length, "big")
|
|
22
|
-
|
|
23
|
-
class Transaction:
|
|
24
|
-
# init
|
|
25
|
-
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
tx_hash: bytes,
|
|
28
|
-
*,
|
|
29
|
-
tree: Optional[MerkleTree] = None,
|
|
30
|
-
global_get_fn: Optional[Callable[[bytes], Optional[bytes]]] = None,
|
|
31
|
-
) -> None:
|
|
32
|
-
self._hash = tx_hash
|
|
33
|
-
self._tree = tree
|
|
34
|
-
self._field_cache: Dict[str, Union[int, bytes]] = {}
|
|
35
|
-
|
|
36
|
-
if self._tree and global_get_fn:
|
|
37
|
-
self._tree.global_get_fn = global_get_fn
|
|
38
|
-
|
|
39
|
-
@classmethod
|
|
40
|
-
def create(
|
|
41
|
-
cls,
|
|
42
|
-
*,
|
|
43
|
-
amount: int,
|
|
44
|
-
balance: int,
|
|
45
|
-
fee: int,
|
|
46
|
-
nonce: int,
|
|
47
|
-
recipient_pk: bytes,
|
|
48
|
-
sender_pk: bytes,
|
|
49
|
-
) -> "Transaction":
|
|
50
|
-
vals: Dict[str, Any] = locals().copy()
|
|
51
|
-
leaves = [
|
|
52
|
-
vals[name] if isinstance(vals[name], bytes) else _int_to_min_bytes(vals[name])
|
|
53
|
-
for name in _FIELD_ORDER
|
|
54
|
-
]
|
|
55
|
-
|
|
56
|
-
tree = MerkleTree.from_leaves(leaves)
|
|
57
|
-
return cls(tx_hash=tree.root_hash, tree=tree)
|
|
58
|
-
|
|
59
|
-
@property
|
|
60
|
-
def hash(self) -> bytes:
|
|
61
|
-
return self._hash
|
|
62
|
-
|
|
63
|
-
def _require_tree(self) -> MerkleTree:
|
|
64
|
-
if not self._tree:
|
|
65
|
-
raise ValueError("Merkle tree unavailable for this Transaction")
|
|
66
|
-
return self._tree
|
|
67
|
-
|
|
68
|
-
def _field(self, idx: int, name: str) -> Union[int, bytes]:
|
|
69
|
-
if name in self._field_cache:
|
|
70
|
-
return self._field_cache[name]
|
|
71
|
-
|
|
72
|
-
raw = self._require_tree().get(idx)
|
|
73
|
-
if raw is None:
|
|
74
|
-
raise ValueError(f"Leaf {idx} (‘{name}’) missing from Merkle tree")
|
|
75
|
-
|
|
76
|
-
value = int.from_bytes(raw, "big") if name in _INT_FIELDS else raw
|
|
77
|
-
self._field_cache[name] = value
|
|
78
|
-
return value
|
|
79
|
-
|
|
80
|
-
def get_amount(self) -> int:
|
|
81
|
-
return self._field(0, "amount")
|
|
82
|
-
|
|
83
|
-
def get_balance(self) -> int:
|
|
84
|
-
return self._field(1, "balance")
|
|
85
|
-
|
|
86
|
-
def get_fee(self) -> int:
|
|
87
|
-
return self._field(2, "fee")
|
|
88
|
-
|
|
89
|
-
def get_nonce(self) -> int:
|
|
90
|
-
return self._field(3, "nonce")
|
|
91
|
-
|
|
92
|
-
def get_recipient_pk(self) -> bytes:
|
|
93
|
-
return self._field(4, "recipient_pk")
|
|
94
|
-
|
|
95
|
-
def get_sender_pk(self) -> bytes:
|
|
96
|
-
return self._field(5, "sender_pk")
|
|
97
|
-
|
|
98
|
-
def sign(self, priv: ed25519.Ed25519PrivateKey) -> bytes:
|
|
99
|
-
return priv.sign(self.hash)
|
|
100
|
-
|
|
101
|
-
def verify_signature(self, sig: bytes, sender_pk: bytes) -> bool:
|
|
102
|
-
try:
|
|
103
|
-
ed25519.Ed25519PublicKey.from_public_bytes(sender_pk).verify(sig, self.hash)
|
|
104
|
-
return True
|
|
105
|
-
except Exception:
|
|
106
|
-
return False
|
astreum/relay/__init__.py
DELETED
|
File without changes
|
astreum/relay/peer.py
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
|
|
2
|
-
from datetime import datetime, timezone
|
|
3
|
-
|
|
4
|
-
class Peer:
|
|
5
|
-
shared_key: bytes
|
|
6
|
-
timestamp: datetime
|
|
7
|
-
def __init__(self, my_sec_key: X25519PrivateKey, peer_pub_key: X25519PublicKey):
|
|
8
|
-
self.shared_key = my_sec_key.exchange(peer_pub_key)
|
|
9
|
-
self.timestamp = datetime.now(timezone.utc)
|
astreum/relay/route.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from typing import Dict, List
|
|
2
|
-
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
|
|
3
|
-
|
|
4
|
-
class Route:
|
|
5
|
-
def __init__(self, relay_public_key: X25519PublicKey, bucket_size: int = 16):
|
|
6
|
-
self.relay_public_key_bytes = relay_public_key.public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw)
|
|
7
|
-
self.bucket_size = bucket_size
|
|
8
|
-
self.buckets: Dict[int, List[X25519PublicKey]] = {
|
|
9
|
-
i: [] for i in range(len(self.relay_public_key_bytes) * 8)
|
|
10
|
-
}
|
|
11
|
-
self.peers = {}
|
|
12
|
-
|
|
13
|
-
@staticmethod
|
|
14
|
-
def _matching_leading_bits(a: bytes, b: bytes) -> int:
|
|
15
|
-
for byte_index, (ba, bb) in enumerate(zip(a, b)):
|
|
16
|
-
diff = ba ^ bb
|
|
17
|
-
if diff:
|
|
18
|
-
return byte_index * 8 + (8 - diff.bit_length())
|
|
19
|
-
return len(a) * 8
|
|
20
|
-
|
|
21
|
-
def add_peer(self, peer_public_key: X25519PublicKey):
|
|
22
|
-
peer_public_key_bytes = peer_public_key.public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw)
|
|
23
|
-
bucket_idx = self._matching_leading_bits(self.relay_public_key_bytes, peer_public_key_bytes)
|
|
24
|
-
if len(self.buckets[bucket_idx]) < self.bucket_size:
|
|
25
|
-
self.buckets[bucket_idx].append(peer_public_key)
|
astreum/relay/setup.py
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import socket, threading
|
|
2
|
-
from queue import Queue
|
|
3
|
-
from typing import Tuple, Optional
|
|
4
|
-
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
5
|
-
from cryptography.hazmat.primitives.asymmetric.x25519 import (
|
|
6
|
-
X25519PrivateKey,
|
|
7
|
-
X25519PublicKey,
|
|
8
|
-
)
|
|
9
|
-
from yourproject.routes import Route
|
|
10
|
-
|
|
11
|
-
def load_x25519(hex_key: Optional[str]) -> X25519PrivateKey:
|
|
12
|
-
"""DH key for relaying (always X25519)."""
|
|
13
|
-
return
|
|
14
|
-
|
|
15
|
-
def load_ed25519(hex_key: Optional[str]) -> Optional[ed25519.Ed25519PrivateKey]:
|
|
16
|
-
"""Signing key for validation (Ed25519), or None if absent."""
|
|
17
|
-
return ed25519.Ed25519PrivateKey.from_private_bytes(bytes.fromhex(hex_key)) \
|
|
18
|
-
if hex_key else None
|
|
19
|
-
|
|
20
|
-
def make_routes(
|
|
21
|
-
relay_pk: X25519PublicKey,
|
|
22
|
-
val_sk: Optional[ed25519.Ed25519PrivateKey]
|
|
23
|
-
) -> Tuple[Route, Optional[Route]]:
|
|
24
|
-
"""Peer route (DH pubkey) + optional validation route (ed pubkey)."""
|
|
25
|
-
peer_rt = Route(relay_pk)
|
|
26
|
-
val_rt = Route(val_sk.public_key()) if val_sk else None
|
|
27
|
-
return peer_rt, val_rt
|
|
28
|
-
|
|
29
|
-
def setup_udp(
|
|
30
|
-
bind_port: int,
|
|
31
|
-
use_ipv6: bool
|
|
32
|
-
) -> Tuple[socket.socket, int, Queue, threading.Thread, threading.Thread]:
|
|
33
|
-
fam = socket.AF_INET6 if use_ipv6 else socket.AF_INET
|
|
34
|
-
sock = socket.socket(fam, socket.SOCK_DGRAM)
|
|
35
|
-
if use_ipv6:
|
|
36
|
-
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
|
37
|
-
sock.bind(("::" if use_ipv6 else "0.0.0.0", bind_port or 0))
|
|
38
|
-
port = sock.getsockname()[1]
|
|
39
|
-
|
|
40
|
-
q = Queue()
|
|
41
|
-
pop = threading.Thread(target=lambda: None, daemon=True)
|
|
42
|
-
proc = threading.Thread(target=lambda: None, daemon=True)
|
|
43
|
-
pop.start(); proc.start()
|
|
44
|
-
return sock, port, q, pop, proc
|
|
45
|
-
|
|
46
|
-
def setup_outgoing(
|
|
47
|
-
use_ipv6: bool
|
|
48
|
-
) -> Tuple[socket.socket, Queue, threading.Thread]:
|
|
49
|
-
fam = socket.AF_INET6 if use_ipv6 else socket.AF_INET
|
|
50
|
-
sock = socket.socket(fam, socket.SOCK_DGRAM)
|
|
51
|
-
q = Queue()
|
|
52
|
-
thr = threading.Thread(target=lambda: None, daemon=True)
|
|
53
|
-
thr.start()
|
|
54
|
-
return sock, q, thr
|
|
55
|
-
|
|
56
|
-
def make_maps():
|
|
57
|
-
"""Empty lookup maps: peers and addresses."""
|
|
58
|
-
return
|
astreum-0.2.29.dist-info/RECORD
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
astreum/__init__.py,sha256=y2Ok3EY_FstcmlVASr80lGR_0w-dH-SXDCCQFmL6uwA,28
|
|
2
|
-
astreum/format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
|
|
3
|
-
astreum/node.py,sha256=OhiApRqQcPc6-CWbk2NeKdOiXQapy0mbl3uLK_xjmYU,28971
|
|
4
|
-
astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
|
|
6
|
-
astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
|
|
7
|
-
astreum/crypto/wesolowski.py,sha256=SUgGXW3Id07dJtWzDcs4dluIhjqbRWQ8YWjn_mK78AQ,4092
|
|
8
|
-
astreum/crypto/x25519.py,sha256=i29v4BmwKRcbz9E7NKqFDQyxzFtJUqN0St9jd7GS1uA,1137
|
|
9
|
-
astreum/lispeum/__init__.py,sha256=K-NDzIjtIsXzC9X7lnYvlvIaVxjFcY7WNsgLIE3DH3U,58
|
|
10
|
-
astreum/lispeum/environment.py,sha256=wolwt9psDl62scgjaVG0G59xlBs1AM4NPgryUbxzG_4,1220
|
|
11
|
-
astreum/lispeum/expression.py,sha256=K8gFifDaHu394bs9qnpvP8tjeiymFGQpnDC_iW9nU4E,2379
|
|
12
|
-
astreum/lispeum/parser.py,sha256=jQRzZYvBuSg8t_bxsbt1-WcHaR_LPveHNX7Qlxhaw-M,1165
|
|
13
|
-
astreum/lispeum/tokenizer.py,sha256=J-I7MEd0r2ZoVqxvRPlu-Afe2ZdM0tKXXhf1R4SxYTo,1429
|
|
14
|
-
astreum/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
astreum/models/account.py,sha256=sHujGSwtV13rvOGJ5LZXuMrJ4F9XUdvyuWKz-zJ9lkE,2986
|
|
16
|
-
astreum/models/accounts.py,sha256=aFSEWlq6zRf65-KGAdNGqEJyNVY3fpKhx8y1vU6sgSc,1164
|
|
17
|
-
astreum/models/block.py,sha256=-5j7uO0woVtNi0h52__e7AxpDQSVhzKUhr6Qc-2xZsE,17870
|
|
18
|
-
astreum/models/merkle.py,sha256=lvWJa9nmrBL0n_2h_uNqpB_9a5s5Hn1FceRLx0IZIVQ,6778
|
|
19
|
-
astreum/models/message.py,sha256=vv8yx-ndVYjCmPM4gXRVMToCTlKY_mflPu0uKsb9iiE,2117
|
|
20
|
-
astreum/models/patricia.py,sha256=ohmXrcaz7Ae561tyC4u4iPOkQPkKr8N0IWJek4upFIg,13392
|
|
21
|
-
astreum/models/transaction.py,sha256=MkLL5YX18kIf9-O4LBaZ4eWjkXDAaYIrDcDehbDZoqg,3038
|
|
22
|
-
astreum/relay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
astreum/relay/peer.py,sha256=94rNkHfsvYfq-ijLDR9QQkEJZ1meMr17HsaNYDBB8kg,398
|
|
24
|
-
astreum/relay/route.py,sha256=enWT_1260LJq-L-zK-jtacQ8LbZGquNO9yj-9IglSXE,1232
|
|
25
|
-
astreum/relay/setup.py,sha256=ynvGaJdlDtw_f5LLiow2Wo7IRzUjvgk8eSr1Sv4_zTg,2090
|
|
26
|
-
astreum/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
-
astreum/storage/object.py,sha256=knFlvw_tpcC4twSu1DGNpHX31wlANN8E5dgEqIfU--Q,2041
|
|
28
|
-
astreum/storage/setup.py,sha256=1-9ztEFI_BvRDvAA0lAn4mFya8iq65THTArlj--M3Hg,626
|
|
29
|
-
astreum-0.2.29.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
30
|
-
astreum-0.2.29.dist-info/METADATA,sha256=JSIc8N98KW4Wmm89uMMFxyJKiEFxIU-zGRjIXf9JL24,5478
|
|
31
|
-
astreum-0.2.29.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
32
|
-
astreum-0.2.29.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
33
|
-
astreum-0.2.29.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|