astreum 0.1.8__py3-none-any.whl → 0.1.10__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/lispeum/storage.py +229 -276
- astreum/machine/__init__.py +352 -254
- astreum/node/__init__.py +143 -54
- astreum/node/models.py +193 -5
- astreum/node/relay/__init__.py +100 -4
- astreum/node/relay/bucket.py +41 -31
- astreum/node/relay/message.py +17 -12
- astreum/node/relay/peer.py +3 -0
- astreum/node/relay/route.py +100 -64
- {astreum-0.1.8.dist-info → astreum-0.1.10.dist-info}/METADATA +11 -7
- {astreum-0.1.8.dist-info → astreum-0.1.10.dist-info}/RECORD +14 -14
- {astreum-0.1.8.dist-info → astreum-0.1.10.dist-info}/WHEEL +1 -1
- {astreum-0.1.8.dist-info → astreum-0.1.10.dist-info}/LICENSE +0 -0
- {astreum-0.1.8.dist-info → astreum-0.1.10.dist-info}/top_level.txt +0 -0
astreum/node/relay/bucket.py
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
K-bucket implementation for Kademlia-style routing in Astreum node.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from typing import List,
|
|
5
|
+
from typing import List, Set
|
|
6
|
+
from .peer import Peer
|
|
6
7
|
|
|
7
8
|
class KBucket:
|
|
8
9
|
"""
|
|
@@ -14,67 +15,76 @@ class KBucket:
|
|
|
14
15
|
This creates a least-recently seen eviction policy.
|
|
15
16
|
"""
|
|
16
17
|
|
|
17
|
-
def __init__(self,
|
|
18
|
+
def __init__(self, k: int = 20):
|
|
18
19
|
"""
|
|
19
20
|
Initialize a k-bucket with a fixed size.
|
|
20
21
|
|
|
21
22
|
Args:
|
|
22
|
-
|
|
23
|
+
k (int): Maximum number of peers in the bucket
|
|
23
24
|
"""
|
|
24
|
-
self.
|
|
25
|
-
self.peers: List[
|
|
25
|
+
self.k = k
|
|
26
|
+
self.peers: List[Peer] = []
|
|
27
|
+
self._peer_ids: Set[bytes] = set() # Track peer IDs for quick lookup
|
|
26
28
|
|
|
27
|
-
def add(self, peer:
|
|
29
|
+
def add(self, peer: Peer) -> bool:
|
|
28
30
|
"""
|
|
29
31
|
Add peer to bucket if not full or if peer exists.
|
|
30
32
|
|
|
31
33
|
Args:
|
|
32
|
-
peer (
|
|
34
|
+
peer (Peer): Peer to add to the bucket
|
|
33
35
|
|
|
34
36
|
Returns:
|
|
35
37
|
bool: True if added/exists, False if bucket full and peer not in bucket
|
|
36
38
|
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
# If peer already in bucket, move to end (most recently seen)
|
|
40
|
+
if peer.public_key in self._peer_ids:
|
|
41
|
+
# Find and remove the peer
|
|
42
|
+
for i, existing_peer in enumerate(self.peers):
|
|
43
|
+
if existing_peer.public_key == peer.public_key:
|
|
44
|
+
del self.peers[i]
|
|
45
|
+
break
|
|
46
|
+
|
|
47
|
+
# Add back at the end (most recently seen)
|
|
40
48
|
self.peers.append(peer)
|
|
49
|
+
peer.update_last_seen()
|
|
41
50
|
return True
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
|
|
52
|
+
# If bucket not full, add peer
|
|
53
|
+
if len(self.peers) < self.k:
|
|
44
54
|
self.peers.append(peer)
|
|
55
|
+
self._peer_ids.add(peer.public_key)
|
|
56
|
+
peer.update_last_seen()
|
|
45
57
|
return True
|
|
46
58
|
|
|
59
|
+
# Bucket full and peer not in bucket
|
|
47
60
|
return False
|
|
48
61
|
|
|
49
|
-
def remove(self, peer:
|
|
62
|
+
def remove(self, peer: Peer) -> bool:
|
|
50
63
|
"""
|
|
51
64
|
Remove peer from bucket.
|
|
52
65
|
|
|
53
66
|
Args:
|
|
54
|
-
peer (
|
|
67
|
+
peer (Peer): Peer to remove
|
|
55
68
|
|
|
56
69
|
Returns:
|
|
57
|
-
bool: True if
|
|
70
|
+
bool: True if removed, False if not in bucket
|
|
58
71
|
"""
|
|
59
|
-
if peer in self.
|
|
60
|
-
self.peers
|
|
61
|
-
|
|
72
|
+
if peer.public_key in self._peer_ids:
|
|
73
|
+
for i, existing_peer in enumerate(self.peers):
|
|
74
|
+
if existing_peer.public_key == peer.public_key:
|
|
75
|
+
del self.peers[i]
|
|
76
|
+
self._peer_ids.remove(peer.public_key)
|
|
77
|
+
return True
|
|
62
78
|
return False
|
|
63
79
|
|
|
64
|
-
def get_peers(self) -> List[
|
|
65
|
-
"""
|
|
66
|
-
Get all peers in the bucket.
|
|
67
|
-
|
|
68
|
-
Returns:
|
|
69
|
-
List[Tuple[str, int]]: List of peer addresses
|
|
70
|
-
"""
|
|
80
|
+
def get_peers(self) -> List[Peer]:
|
|
81
|
+
"""Get all peers in the bucket."""
|
|
71
82
|
return self.peers.copy()
|
|
72
83
|
|
|
73
|
-
def
|
|
74
|
-
"""
|
|
75
|
-
|
|
84
|
+
def contains(self, peer_id: bytes) -> bool:
|
|
85
|
+
"""Check if a peer ID is in the bucket."""
|
|
86
|
+
return peer_id in self._peer_ids
|
|
76
87
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"""
|
|
88
|
+
def __len__(self) -> int:
|
|
89
|
+
"""Get the number of peers in the bucket."""
|
|
80
90
|
return len(self.peers)
|
astreum/node/relay/message.py
CHANGED
|
@@ -3,25 +3,30 @@ Message related classes and utilities for Astreum node network.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import struct
|
|
6
|
-
from enum import
|
|
6
|
+
from enum import IntEnum, auto
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from typing import Optional
|
|
9
9
|
from astreum.utils.bytes_format import encode, decode
|
|
10
10
|
|
|
11
|
-
class Topic(
|
|
11
|
+
class Topic(IntEnum):
|
|
12
12
|
"""
|
|
13
13
|
Enum for different message topics in the Astreum network.
|
|
14
14
|
"""
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
PEER_ROUTE = 1
|
|
16
|
+
LATEST_BLOCK_REQUEST = 2
|
|
17
|
+
LATEST_BLOCK_RESPONSE = 3
|
|
18
|
+
GET_BLOCKS = 4
|
|
19
|
+
BLOCKS = 5
|
|
20
|
+
TRANSACTION = 6
|
|
21
|
+
BLOCK_COMMIT = 7
|
|
22
|
+
OBJECT_REQUEST = 8
|
|
23
|
+
OBJECT_RESPONSE = 9
|
|
24
|
+
PING = 10
|
|
25
|
+
PONG = 11
|
|
26
|
+
ROUTE = 12
|
|
27
|
+
ROUTE_REQUEST = 13
|
|
28
|
+
LATEST_BLOCK = 14
|
|
29
|
+
BLOCK = 15
|
|
25
30
|
|
|
26
31
|
def to_bytes(self) -> bytes:
|
|
27
32
|
"""
|
astreum/node/relay/peer.py
CHANGED
|
@@ -151,6 +151,9 @@ class PeerManager:
|
|
|
151
151
|
"""
|
|
152
152
|
Calculate the XOR distance between our node ID and the given public key.
|
|
153
153
|
|
|
154
|
+
In Kademlia, peers are organized into buckets based on the XOR distance.
|
|
155
|
+
The bucket index (0-255) represents the position of the first bit that differs.
|
|
156
|
+
|
|
154
157
|
Args:
|
|
155
158
|
public_key (bytes): The remote node's public key
|
|
156
159
|
|
astreum/node/relay/route.py
CHANGED
|
@@ -11,25 +11,32 @@ class RouteTable:
|
|
|
11
11
|
Kademlia-style routing table using k-buckets.
|
|
12
12
|
|
|
13
13
|
The routing table consists of k-buckets, each covering a specific range of distances.
|
|
14
|
-
|
|
14
|
+
In Kademlia, bucket index (i) contains nodes that share exactly i bits with the local node:
|
|
15
|
+
- Bucket 0: Contains peers that don't share the first bit with our node ID
|
|
16
|
+
- Bucket 1: Contains peers that share the first bit, but differ on the second bit
|
|
17
|
+
- Bucket 2: Contains peers that share the first two bits, but differ on the third bit
|
|
18
|
+
- And so on...
|
|
19
|
+
|
|
20
|
+
This structuring ensures efficient routing to any node in the network.
|
|
15
21
|
"""
|
|
16
22
|
|
|
17
|
-
def __init__(self,
|
|
23
|
+
def __init__(self, relay):
|
|
18
24
|
"""
|
|
19
25
|
Initialize the routing table.
|
|
20
26
|
|
|
21
27
|
Args:
|
|
22
|
-
|
|
23
|
-
our_node_id (bytes): Our node's unique identifier
|
|
28
|
+
relay: The relay instance this route table belongs to
|
|
24
29
|
"""
|
|
25
|
-
self.
|
|
26
|
-
self.
|
|
27
|
-
self.
|
|
28
|
-
|
|
30
|
+
self.relay = relay
|
|
31
|
+
self.our_node_id = relay.node_id
|
|
32
|
+
self.bucket_size = relay.config.get('max_peers_per_bucket', 20)
|
|
33
|
+
# Initialize buckets - for a 256-bit key, we need up to 256 buckets
|
|
34
|
+
self.buckets = {i: KBucket(k=self.bucket_size) for i in range(256)}
|
|
35
|
+
self.peer_manager = PeerManager(self.our_node_id)
|
|
29
36
|
|
|
30
37
|
def add_peer(self, peer: Peer) -> bool:
|
|
31
38
|
"""
|
|
32
|
-
Add a peer to the appropriate k-bucket based on
|
|
39
|
+
Add a peer to the appropriate k-bucket based on bit prefix matching.
|
|
33
40
|
|
|
34
41
|
Args:
|
|
35
42
|
peer (Peer): The peer to add
|
|
@@ -37,14 +44,32 @@ class RouteTable:
|
|
|
37
44
|
Returns:
|
|
38
45
|
bool: True if the peer was added, False otherwise
|
|
39
46
|
"""
|
|
40
|
-
|
|
47
|
+
# Calculate the number of matching prefix bits
|
|
48
|
+
matching_bits = self.peer_manager.calculate_distance(peer.public_key)
|
|
49
|
+
|
|
50
|
+
# Add to the appropriate bucket based on the number of matching bits
|
|
51
|
+
return self.buckets[matching_bits].add(peer)
|
|
52
|
+
|
|
53
|
+
def update_peer(self, addr: tuple, public_key: bytes, difficulty: int = 1) -> Peer:
|
|
54
|
+
"""
|
|
55
|
+
Update or add a peer to the routing table.
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
Args:
|
|
58
|
+
addr: Tuple of (ip, port)
|
|
59
|
+
public_key: Peer's public key
|
|
60
|
+
difficulty: Peer's proof-of-work difficulty
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
Returns:
|
|
63
|
+
Peer: The updated or added peer
|
|
64
|
+
"""
|
|
65
|
+
# Create or update the peer
|
|
66
|
+
peer = self.peer_manager.add_or_update_peer(addr, public_key)
|
|
67
|
+
peer.difficulty = difficulty
|
|
68
|
+
|
|
69
|
+
# Add to the appropriate bucket
|
|
70
|
+
self.add_peer(peer)
|
|
71
|
+
|
|
72
|
+
return peer
|
|
48
73
|
|
|
49
74
|
def remove_peer(self, peer: Peer) -> bool:
|
|
50
75
|
"""
|
|
@@ -56,70 +81,81 @@ class RouteTable:
|
|
|
56
81
|
Returns:
|
|
57
82
|
bool: True if the peer was removed, False otherwise
|
|
58
83
|
"""
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return self.buckets[distance].remove(peer.address)
|
|
84
|
+
matching_bits = self.peer_manager.calculate_distance(peer.public_key)
|
|
85
|
+
if matching_bits in self.buckets:
|
|
86
|
+
return self.buckets[matching_bits].remove(peer)
|
|
63
87
|
return False
|
|
64
|
-
|
|
65
|
-
def get_closest_peers(self, target_id: bytes,
|
|
88
|
+
|
|
89
|
+
def get_closest_peers(self, target_id: bytes, count: int = 3) -> List[Peer]:
|
|
66
90
|
"""
|
|
67
|
-
Get the closest peers to
|
|
91
|
+
Get the closest peers to the target ID.
|
|
68
92
|
|
|
69
93
|
Args:
|
|
70
|
-
target_id
|
|
71
|
-
|
|
94
|
+
target_id: Target ID to find peers close to
|
|
95
|
+
count: Maximum number of peers to return
|
|
72
96
|
|
|
73
97
|
Returns:
|
|
74
|
-
List
|
|
98
|
+
List of peers closest to the target ID
|
|
75
99
|
"""
|
|
76
|
-
# Calculate
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
# Calculate the number of matching prefix bits with the target
|
|
101
|
+
matching_bits = self.peer_manager.calculate_distance(target_id)
|
|
102
|
+
|
|
103
|
+
closest_peers = []
|
|
104
|
+
|
|
105
|
+
# First check the exact matching bucket
|
|
106
|
+
if matching_bits in self.buckets:
|
|
107
|
+
bucket_peers = self.buckets[matching_bits].get_peers()
|
|
108
|
+
closest_peers.extend(bucket_peers)
|
|
109
|
+
|
|
110
|
+
# If we need more peers, also check adjacent buckets (farther first)
|
|
111
|
+
if len(closest_peers) < count:
|
|
112
|
+
# Check buckets with fewer matching bits (higher XOR distance)
|
|
113
|
+
for i in range(matching_bits - 1, -1, -1):
|
|
114
|
+
if i in self.buckets:
|
|
115
|
+
bucket_peers = self.buckets[i].get_peers()
|
|
116
|
+
closest_peers.extend(bucket_peers)
|
|
117
|
+
if len(closest_peers) >= count:
|
|
118
|
+
break
|
|
119
|
+
|
|
120
|
+
# If still not enough, check buckets with more matching bits
|
|
121
|
+
if len(closest_peers) < count:
|
|
122
|
+
for i in range(matching_bits + 1, 256):
|
|
123
|
+
if i in self.buckets:
|
|
124
|
+
bucket_peers = self.buckets[i].get_peers()
|
|
125
|
+
closest_peers.extend(bucket_peers)
|
|
126
|
+
if len(closest_peers) >= count:
|
|
127
|
+
break
|
|
128
|
+
|
|
129
|
+
# Return the closest peers, limited by count
|
|
130
|
+
return closest_peers[:count]
|
|
96
131
|
|
|
97
|
-
def
|
|
132
|
+
def get_bucket_peers(self, bucket_index: int) -> List[Peer]:
|
|
98
133
|
"""
|
|
99
|
-
Get
|
|
134
|
+
Get all peers from a specific bucket.
|
|
100
135
|
|
|
136
|
+
Args:
|
|
137
|
+
bucket_index: Index of the bucket to get peers from
|
|
138
|
+
|
|
101
139
|
Returns:
|
|
102
|
-
|
|
140
|
+
List of peers in the bucket
|
|
103
141
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
142
|
+
if bucket_index in self.buckets:
|
|
143
|
+
return self.buckets[bucket_index].get_peers()
|
|
144
|
+
return []
|
|
145
|
+
|
|
146
|
+
def has_peer(self, addr: tuple) -> bool:
|
|
107
147
|
"""
|
|
108
|
-
|
|
148
|
+
Check if a peer with the given address exists in the routing table.
|
|
109
149
|
|
|
110
150
|
Args:
|
|
111
|
-
|
|
151
|
+
addr: Tuple of (ip, port)
|
|
112
152
|
|
|
113
153
|
Returns:
|
|
114
|
-
|
|
154
|
+
bool: True if the peer exists, False otherwise
|
|
115
155
|
"""
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if peer:
|
|
123
|
-
peers.append(peer)
|
|
124
|
-
|
|
125
|
-
return peers
|
|
156
|
+
return self.peer_manager.get_peer_by_address(addr) is not None
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def num_buckets(self) -> int:
|
|
160
|
+
"""Get the number of active buckets."""
|
|
161
|
+
return len(self.buckets)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
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
|
|
@@ -11,6 +11,8 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Requires-Python: >=3.8
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
+
Requires-Dist: pycryptodomex==3.21.0
|
|
15
|
+
Requires-Dist: cryptography==44.0.2
|
|
14
16
|
|
|
15
17
|
# lib
|
|
16
18
|
|
|
@@ -26,9 +28,10 @@ When initializing an Astreum Node, you need to provide a configuration dictionar
|
|
|
26
28
|
|
|
27
29
|
| Parameter | Type | Default | Description |
|
|
28
30
|
|-----------|------|---------|-------------|
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
31
|
+
| `private_key` | string | Auto-generated | Hex string of Ed25519 private key. If not provided, a new keypair will be generated automatically |
|
|
32
|
+
| `storage_path` | string | "storage" | Path to store data |
|
|
33
|
+
| `max_storage_space` | int | 1073741824 (1GB) | Maximum storage space in bytes |
|
|
34
|
+
| `max_object_recursion` | int | 50 | Maximum recursion depth for resolving nested objects |
|
|
32
35
|
|
|
33
36
|
### Network Configuration
|
|
34
37
|
|
|
@@ -38,15 +41,17 @@ When initializing an Astreum Node, you need to provide a configuration dictionar
|
|
|
38
41
|
| `incoming_port` | int | 7373 | Port to listen for incoming messages |
|
|
39
42
|
| `max_message_size` | int | 65536 | Maximum size of UDP datagrams in bytes |
|
|
40
43
|
| `num_workers` | int | 4 | Number of worker threads for message processing |
|
|
44
|
+
| `network_request_timeout` | float | 5.0 | Maximum time (in seconds) to wait for network object requests |
|
|
41
45
|
|
|
42
46
|
### Route Configuration
|
|
43
47
|
|
|
44
48
|
| Parameter | Type | Default | Description |
|
|
45
49
|
|-----------|------|---------|-------------|
|
|
46
|
-
| `peer_route` | bool | False | Whether to participate in the peer discovery route |
|
|
47
50
|
| `validation_route` | bool | False | Whether to participate in the block validation route |
|
|
48
51
|
| `bootstrap_peers` | list | [] | List of bootstrap peers in the format `[("hostname", port), ...]` |
|
|
49
52
|
|
|
53
|
+
> **Note:** The peer route is always enabled as it's necessary for object discovery and retrieval.
|
|
54
|
+
|
|
50
55
|
### Example Usage
|
|
51
56
|
|
|
52
57
|
```python
|
|
@@ -54,8 +59,7 @@ from astreum.node import Node
|
|
|
54
59
|
|
|
55
60
|
# Configuration dictionary
|
|
56
61
|
config = {
|
|
57
|
-
"
|
|
58
|
-
"followed_chain_id": b"main-chain-id-goes-here",
|
|
62
|
+
"private_key": "my-private-key-goes-here",
|
|
59
63
|
"storage_path": "./data/node1",
|
|
60
64
|
"incoming_port": 7373,
|
|
61
65
|
"use_ipv6": False,
|
|
@@ -2,7 +2,7 @@ astreum/__init__.py,sha256=di8SwGUW1lNKUwvNWCjH9eLmz__sk1SbtuNZVjjpRe4,59
|
|
|
2
2
|
astreum/lispeum/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
astreum/lispeum/expression.py,sha256=3zOEoXFHpzEFUIi1clONY55WYAh5K0YkYhaLmtvQj0I,2939
|
|
4
4
|
astreum/lispeum/parser.py,sha256=SU8mjPj1ub4xQbU4CeX15HmKZAj4vI6TeefX2B72VCo,1191
|
|
5
|
-
astreum/lispeum/storage.py,sha256=
|
|
5
|
+
astreum/lispeum/storage.py,sha256=34BXwn6RVPqdGc6q-SxHT8Qn-lH8YDtnvwJh_7E-gNQ,13948
|
|
6
6
|
astreum/lispeum/tokenizer.py,sha256=4obr1Jt-k1TqhsImHWUn7adQl9Ks5_VmcEFOTlQwocQ,1437
|
|
7
7
|
astreum/lispeum/special/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
astreum/lispeum/special/definition.py,sha256=ukQJ-Mz57bpqbTPQiwmevdE4uxec3Zt--apT3VhUYqU,840
|
|
@@ -17,21 +17,21 @@ astreum/lispeum/special/list/position.py,sha256=1EcD5fzfjUCUhHCk8iotFoWdeE9Z2Rjj
|
|
|
17
17
|
astreum/lispeum/special/list/remove.py,sha256=EPhkWFwyKG8HyWPheVvtxCvMaEGvODFUbx7h1fli_hg,690
|
|
18
18
|
astreum/lispeum/special/number/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
astreum/lispeum/special/number/addition.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
astreum/machine/__init__.py,sha256=
|
|
20
|
+
astreum/machine/__init__.py,sha256=GOdZl1tS9uIJHbq5WVcplifMDPDLQroX7CVew-K2YbA,15262
|
|
21
21
|
astreum/machine/environment.py,sha256=K0084U6B7wwjrDZ9b2_7cEcbBzsB7UOy_Zpbrr7B3GY,834
|
|
22
22
|
astreum/machine/error.py,sha256=MvqBaZZt33rNELNhUJ2lER3TE3aS8WVqsWF2hz2AwoA,38
|
|
23
|
-
astreum/node/__init__.py,sha256=
|
|
24
|
-
astreum/node/models.py,sha256=
|
|
25
|
-
astreum/node/relay/__init__.py,sha256=
|
|
26
|
-
astreum/node/relay/bucket.py,sha256=
|
|
23
|
+
astreum/node/__init__.py,sha256=wvmMMACicwhJ-ipSLpR1rsEUXWuHaZ8fnsBCkUA_RA8,22387
|
|
24
|
+
astreum/node/models.py,sha256=MScDCNEpR-SfaFsRSU567mVuZRhH1Lqc7gmlqb3j-nI,10980
|
|
25
|
+
astreum/node/relay/__init__.py,sha256=gQNYDxllkjZqE6bvgPOYkKu3QHkjPFn11RvtP-BxtKI,13994
|
|
26
|
+
astreum/node/relay/bucket.py,sha256=pcmollbbM-xeHlmDxLZnzvf0Ut-9v9RoN6SijYiQuu8,2893
|
|
27
27
|
astreum/node/relay/envelope.py,sha256=TfkynttoPX7smvMV7xEAdtIlfz-Z-EZjuhZ826csZxA,10078
|
|
28
|
-
astreum/node/relay/message.py,sha256=
|
|
29
|
-
astreum/node/relay/peer.py,sha256=
|
|
30
|
-
astreum/node/relay/route.py,sha256=
|
|
28
|
+
astreum/node/relay/message.py,sha256=uezmGjNaQK4fZmYQLCHd2YpiosaaFb8DOa3H58HS1jA,2887
|
|
29
|
+
astreum/node/relay/peer.py,sha256=DlvTR9j0BZQ1dW-p_9UGgfLvQqwNdpNLMSCYEW4FhyI,5899
|
|
30
|
+
astreum/node/relay/route.py,sha256=fyOSsAe1mfsCVeN6LtQ_OEUEb1FiC5dobZBEJKNGU9U,5814
|
|
31
31
|
astreum/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
astreum/utils/bytes_format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
|
|
33
|
-
astreum-0.1.
|
|
34
|
-
astreum-0.1.
|
|
35
|
-
astreum-0.1.
|
|
36
|
-
astreum-0.1.
|
|
37
|
-
astreum-0.1.
|
|
33
|
+
astreum-0.1.10.dist-info/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
34
|
+
astreum-0.1.10.dist-info/METADATA,sha256=50hGAAYObIlHpnh2ikWSAALUtOIwmw9O_U6c1qLCre8,2942
|
|
35
|
+
astreum-0.1.10.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
36
|
+
astreum-0.1.10.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
37
|
+
astreum-0.1.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|