astreum 0.3.16__py3-none-any.whl → 0.3.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.
- astreum/__init__.py +1 -2
- astreum/communication/__init__.py +15 -11
- astreum/communication/difficulty.py +39 -0
- astreum/communication/disconnect.py +57 -0
- astreum/communication/handlers/handshake.py +105 -62
- astreum/communication/handlers/object_request.py +179 -149
- astreum/communication/handlers/object_response.py +7 -1
- astreum/communication/handlers/ping.py +9 -0
- astreum/communication/handlers/route_request.py +7 -1
- astreum/communication/handlers/route_response.py +7 -1
- astreum/communication/incoming_queue.py +96 -0
- astreum/communication/message_pow.py +36 -0
- astreum/communication/models/peer.py +4 -0
- astreum/communication/models/ping.py +27 -6
- astreum/communication/models/route.py +4 -0
- astreum/communication/{start.py → node.py} +10 -11
- astreum/communication/outgoing_queue.py +108 -0
- astreum/communication/processors/incoming.py +110 -37
- astreum/communication/processors/outgoing.py +35 -2
- astreum/communication/processors/peer.py +133 -58
- astreum/communication/setup.py +272 -113
- astreum/communication/util.py +14 -0
- astreum/node.py +99 -92
- astreum/storage/actions/get.py +79 -48
- astreum/storage/actions/set.py +171 -156
- astreum/storage/providers.py +24 -0
- astreum/storage/setup.py +23 -22
- astreum/utils/config.py +234 -45
- astreum/utils/logging.py +1 -1
- astreum/{consensus → validation}/__init__.py +0 -4
- astreum/validation/constants.py +2 -0
- astreum/{consensus → validation}/genesis.py +4 -6
- astreum/validation/models/block.py +544 -0
- astreum/validation/models/fork.py +511 -0
- astreum/{consensus → validation}/models/receipt.py +17 -4
- astreum/{consensus → validation}/models/transaction.py +45 -3
- astreum/validation/node.py +190 -0
- astreum/{consensus → validation}/validator.py +1 -1
- astreum/validation/workers/__init__.py +8 -0
- astreum/{consensus → validation}/workers/validation.py +360 -333
- astreum/verification/__init__.py +4 -0
- astreum/{consensus/workers/discovery.py → verification/discover.py} +1 -1
- astreum/verification/node.py +61 -0
- astreum/verification/worker.py +183 -0
- {astreum-0.3.16.dist-info → astreum-0.3.46.dist-info}/METADATA +43 -9
- astreum-0.3.46.dist-info/RECORD +79 -0
- astreum/consensus/models/block.py +0 -364
- astreum/consensus/models/chain.py +0 -66
- astreum/consensus/models/fork.py +0 -100
- astreum/consensus/setup.py +0 -83
- astreum/consensus/start.py +0 -67
- astreum/consensus/workers/__init__.py +0 -9
- astreum/consensus/workers/verify.py +0 -90
- astreum-0.3.16.dist-info/RECORD +0 -72
- /astreum/{consensus → validation}/models/__init__.py +0 -0
- /astreum/{consensus → validation}/models/account.py +0 -0
- /astreum/{consensus → validation}/models/accounts.py +0 -0
- {astreum-0.3.16.dist-info → astreum-0.3.46.dist-info}/WHEEL +0 -0
- {astreum-0.3.16.dist-info → astreum-0.3.46.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.3.16.dist-info → astreum-0.3.46.dist-info}/top_level.txt +0 -0
astreum/storage/actions/get.py
CHANGED
|
@@ -4,6 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
6
|
from ..models.atom import Atom
|
|
7
|
+
from ..providers import provider_payload_for_id
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def _hot_storage_get(self, key: bytes) -> Optional[Atom]:
|
|
@@ -24,11 +25,12 @@ def _network_get(self, key: bytes) -> Optional[Atom]:
|
|
|
24
25
|
return None
|
|
25
26
|
self.logger.debug("Attempting network fetch for %s", key.hex())
|
|
26
27
|
try:
|
|
27
|
-
from ...communication.handlers.object_request import (
|
|
28
|
-
ObjectRequest,
|
|
29
|
-
ObjectRequestType,
|
|
30
|
-
)
|
|
31
|
-
from ...communication.models.message import Message, MessageTopic
|
|
28
|
+
from ...communication.handlers.object_request import (
|
|
29
|
+
ObjectRequest,
|
|
30
|
+
ObjectRequestType,
|
|
31
|
+
)
|
|
32
|
+
from ...communication.models.message import Message, MessageTopic
|
|
33
|
+
from ...communication.outgoing_queue import enqueue_outgoing
|
|
32
34
|
except Exception as exc:
|
|
33
35
|
self.logger.warning(
|
|
34
36
|
"Communication module unavailable; cannot fetch %s: %s",
|
|
@@ -71,12 +73,24 @@ def _network_get(self, key: bytes) -> Optional[Atom]:
|
|
|
71
73
|
self.logger.warning("Failed to track object request for %s: %s", key.hex(), exc)
|
|
72
74
|
|
|
73
75
|
try:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
closest_peer.
|
|
79
|
-
)
|
|
76
|
+
queued = enqueue_outgoing(
|
|
77
|
+
self,
|
|
78
|
+
closest_peer.address,
|
|
79
|
+
message=message,
|
|
80
|
+
difficulty=closest_peer.difficulty,
|
|
81
|
+
)
|
|
82
|
+
if queued:
|
|
83
|
+
self.logger.debug(
|
|
84
|
+
"Queued OBJECT_GET for %s to peer %s",
|
|
85
|
+
key.hex(),
|
|
86
|
+
closest_peer.address,
|
|
87
|
+
)
|
|
88
|
+
else:
|
|
89
|
+
self.logger.debug(
|
|
90
|
+
"Dropped OBJECT_GET for %s to peer %s",
|
|
91
|
+
key.hex(),
|
|
92
|
+
closest_peer.address,
|
|
93
|
+
)
|
|
80
94
|
except Exception as exc:
|
|
81
95
|
self.logger.warning(
|
|
82
96
|
"Failed to queue OBJECT_GET for %s to %s: %s",
|
|
@@ -102,43 +116,60 @@ def storage_get(self, key: bytes) -> Optional[Atom]:
|
|
|
102
116
|
if not self.is_connected:
|
|
103
117
|
return None
|
|
104
118
|
|
|
105
|
-
|
|
106
|
-
if
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
119
|
+
provider_id = self.storage_index.get(key)
|
|
120
|
+
if provider_id is not None:
|
|
121
|
+
provider_payload = provider_payload_for_id(self, provider_id)
|
|
122
|
+
if provider_payload is not None:
|
|
123
|
+
try:
|
|
124
|
+
from ...communication.handlers.object_response import decode_object_provider
|
|
125
|
+
from ...communication.handlers.object_request import (
|
|
126
|
+
ObjectRequest,
|
|
127
|
+
ObjectRequestType,
|
|
128
|
+
)
|
|
129
|
+
from ...communication.models.message import Message, MessageTopic
|
|
130
|
+
from ...communication.outgoing_queue import enqueue_outgoing
|
|
131
|
+
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PublicKey
|
|
132
|
+
|
|
133
|
+
provider_key, provider_address, provider_port = decode_object_provider(provider_payload)
|
|
134
|
+
provider_public_key = X25519PublicKey.from_public_bytes(provider_key)
|
|
135
|
+
shared_key_bytes = self.relay_secret_key.exchange(provider_public_key)
|
|
136
|
+
|
|
137
|
+
obj_req = ObjectRequest(
|
|
138
|
+
type=ObjectRequestType.OBJECT_GET,
|
|
139
|
+
data=b"",
|
|
140
|
+
atom_id=key,
|
|
141
|
+
)
|
|
142
|
+
message = Message(
|
|
143
|
+
topic=MessageTopic.OBJECT_REQUEST,
|
|
144
|
+
content=obj_req.to_bytes(),
|
|
145
|
+
sender=self.relay_public_key,
|
|
146
|
+
)
|
|
147
|
+
message.encrypt(shared_key_bytes)
|
|
148
|
+
self.add_atom_req(key)
|
|
149
|
+
queued = enqueue_outgoing(
|
|
150
|
+
self,
|
|
151
|
+
(provider_address, provider_port),
|
|
152
|
+
message=message,
|
|
153
|
+
difficulty=1,
|
|
154
|
+
)
|
|
155
|
+
if queued:
|
|
156
|
+
self.logger.debug(
|
|
157
|
+
"Requested atom %s from indexed provider %s:%s",
|
|
158
|
+
key.hex(),
|
|
159
|
+
provider_address,
|
|
160
|
+
provider_port,
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
self.logger.debug(
|
|
164
|
+
"Dropped request for atom %s to indexed provider %s:%s",
|
|
165
|
+
key.hex(),
|
|
166
|
+
provider_address,
|
|
167
|
+
provider_port,
|
|
168
|
+
)
|
|
169
|
+
except Exception as exc:
|
|
170
|
+
self.logger.warning("Failed indexed fetch for %s: %s", key.hex(), exc)
|
|
171
|
+
return None
|
|
172
|
+
self.logger.warning("Unknown provider id %s for %s", provider_id, key.hex())
|
|
142
173
|
|
|
143
174
|
self.logger.debug("Falling back to network fetch for %s", key.hex())
|
|
144
175
|
return self._network_get(key)
|
astreum/storage/actions/set.py
CHANGED
|
@@ -1,159 +1,160 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import socket
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
from cryptography.hazmat.primitives import serialization
|
|
7
|
-
|
|
8
|
-
from ..models.atom import Atom
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
self.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
atom_hex =
|
|
41
|
-
if not self.config["cold_storage_path"]:
|
|
42
|
-
node_logger.debug("Cold storage disabled; skipping atom %s", atom_hex)
|
|
43
|
-
return
|
|
44
|
-
atom_bytes = atom.to_bytes()
|
|
45
|
-
projected = self.cold_storage_size + len(atom_bytes)
|
|
46
|
-
cold_limit = self.config["cold_storage_limit"]
|
|
47
|
-
if cold_limit and projected > cold_limit:
|
|
48
|
-
node_logger.warning(
|
|
49
|
-
"Cold storage limit reached (%s > %s); skipping atom %s",
|
|
50
|
-
projected,
|
|
51
|
-
cold_limit,
|
|
52
|
-
atom_hex,
|
|
53
|
-
)
|
|
54
|
-
return
|
|
55
|
-
directory = Path(self.config["cold_storage_path"])
|
|
56
|
-
if not directory.exists():
|
|
57
|
-
node_logger.warning(
|
|
58
|
-
"Cold storage path %s missing; skipping atom %s",
|
|
59
|
-
directory,
|
|
60
|
-
atom_hex,
|
|
61
|
-
)
|
|
62
|
-
return
|
|
63
|
-
filename = f"{atom_hex.upper()}.bin"
|
|
64
|
-
file_path = directory / filename
|
|
65
|
-
try:
|
|
66
|
-
file_path.write_bytes(atom_bytes)
|
|
67
|
-
self.cold_storage_size = projected
|
|
68
|
-
node_logger.debug("Persisted atom %s to cold storage", atom_hex)
|
|
69
|
-
except OSError as exc:
|
|
70
|
-
node_logger.error(
|
|
71
|
-
"Failed writing atom %s to cold storage %s: %s",
|
|
72
|
-
atom_hex,
|
|
73
|
-
file_path,
|
|
74
|
-
exc,
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def _network_set(self,
|
|
79
|
-
"""Advertise an atom to the closest known peer so they can fetch it from us."""
|
|
80
|
-
node_logger = self.logger
|
|
81
|
-
|
|
82
|
-
atom_hex = atom_id.hex()
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import socket
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from cryptography.hazmat.primitives import serialization
|
|
7
|
+
|
|
8
|
+
from ..models.atom import Atom
|
|
9
|
+
from ..providers import provider_id_for_payload
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _hot_storage_set(self, key: bytes, value: Atom) -> bool:
|
|
13
|
+
"""Store atom in hot storage without exceeding the configured limit."""
|
|
14
|
+
node_logger = self.logger
|
|
15
|
+
projected = self.hot_storage_size + value.size
|
|
16
|
+
hot_limit = self.config["hot_storage_limit"]
|
|
17
|
+
if projected > hot_limit:
|
|
18
|
+
node_logger.warning(
|
|
19
|
+
"Hot storage limit reached (%s > %s); skipping atom %s",
|
|
20
|
+
projected,
|
|
21
|
+
hot_limit,
|
|
22
|
+
key.hex(),
|
|
23
|
+
)
|
|
24
|
+
return False
|
|
25
|
+
|
|
26
|
+
self.hot_storage[key] = value
|
|
27
|
+
self.hot_storage_size = projected
|
|
28
|
+
node_logger.debug(
|
|
29
|
+
"Stored atom %s in hot storage (bytes=%s, total=%s)",
|
|
30
|
+
key.hex(),
|
|
31
|
+
value.size,
|
|
32
|
+
projected,
|
|
33
|
+
)
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _cold_storage_set(self, key: bytes, atom: Atom) -> None:
|
|
38
|
+
"""Persist an atom into the cold storage directory if it already exists."""
|
|
39
|
+
node_logger = self.logger
|
|
40
|
+
atom_hex = key.hex()
|
|
41
|
+
if not self.config["cold_storage_path"]:
|
|
42
|
+
node_logger.debug("Cold storage disabled; skipping atom %s", atom_hex)
|
|
43
|
+
return
|
|
44
|
+
atom_bytes = atom.to_bytes()
|
|
45
|
+
projected = self.cold_storage_size + len(atom_bytes)
|
|
46
|
+
cold_limit = self.config["cold_storage_limit"]
|
|
47
|
+
if cold_limit and projected > cold_limit:
|
|
48
|
+
node_logger.warning(
|
|
49
|
+
"Cold storage limit reached (%s > %s); skipping atom %s",
|
|
50
|
+
projected,
|
|
51
|
+
cold_limit,
|
|
52
|
+
atom_hex,
|
|
53
|
+
)
|
|
54
|
+
return
|
|
55
|
+
directory = Path(self.config["cold_storage_path"])
|
|
56
|
+
if not directory.exists():
|
|
57
|
+
node_logger.warning(
|
|
58
|
+
"Cold storage path %s missing; skipping atom %s",
|
|
59
|
+
directory,
|
|
60
|
+
atom_hex,
|
|
61
|
+
)
|
|
62
|
+
return
|
|
63
|
+
filename = f"{atom_hex.upper()}.bin"
|
|
64
|
+
file_path = directory / filename
|
|
65
|
+
try:
|
|
66
|
+
file_path.write_bytes(atom_bytes)
|
|
67
|
+
self.cold_storage_size = projected
|
|
68
|
+
node_logger.debug("Persisted atom %s to cold storage", atom_hex)
|
|
69
|
+
except OSError as exc:
|
|
70
|
+
node_logger.error(
|
|
71
|
+
"Failed writing atom %s to cold storage %s: %s",
|
|
72
|
+
atom_hex,
|
|
73
|
+
file_path,
|
|
74
|
+
exc,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _network_set(self, atom_id: bytes) -> None:
|
|
79
|
+
"""Advertise an atom id to the closest known peer so they can fetch it from us."""
|
|
80
|
+
node_logger = self.logger
|
|
81
|
+
atom_hex = atom_id.hex()
|
|
83
82
|
try:
|
|
84
83
|
from ...communication.handlers.object_request import (
|
|
85
84
|
ObjectRequest,
|
|
86
85
|
ObjectRequestType,
|
|
87
86
|
)
|
|
88
87
|
from ...communication.models.message import Message, MessageTopic
|
|
88
|
+
from ...communication.outgoing_queue import enqueue_outgoing
|
|
89
89
|
except Exception as exc:
|
|
90
90
|
node_logger.warning(
|
|
91
91
|
"Communication module unavailable; cannot advertise atom %s: %s",
|
|
92
92
|
atom_hex,
|
|
93
|
-
exc,
|
|
94
|
-
)
|
|
95
|
-
return
|
|
96
|
-
|
|
97
|
-
try:
|
|
98
|
-
provider_ip, provider_port = self.incoming_socket.getsockname()[:2]
|
|
99
|
-
except Exception as exc:
|
|
100
|
-
node_logger.warning(
|
|
101
|
-
"Unable to determine provider address for atom %s: %s",
|
|
102
|
-
atom_hex,
|
|
103
|
-
exc,
|
|
104
|
-
)
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
try:
|
|
108
|
-
provider_ip_bytes = socket.inet_aton(provider_ip)
|
|
109
|
-
provider_port_bytes = int(provider_port).to_bytes(2, "big", signed=False)
|
|
110
|
-
provider_key_bytes = self.relay_public_key_bytes
|
|
111
|
-
except Exception as exc:
|
|
112
|
-
node_logger.warning("Unable to encode provider info for %s: %s", atom_hex, exc)
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
provider_payload = provider_key_bytes + provider_ip_bytes + provider_port_bytes
|
|
116
|
-
|
|
117
|
-
try:
|
|
118
|
-
closest_peer = self.peer_route.closest_peer_for_hash(atom_id)
|
|
119
|
-
except Exception as exc:
|
|
120
|
-
node_logger.warning("Peer lookup failed for atom %s: %s", atom_hex, exc)
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
is_self_closest = False
|
|
124
|
-
if closest_peer is None or closest_peer.address is None:
|
|
125
|
-
is_self_closest = True
|
|
126
|
-
else:
|
|
127
|
-
try:
|
|
128
|
-
from ...communication.util import xor_distance
|
|
129
|
-
except Exception as exc:
|
|
130
|
-
node_logger.warning("Failed to import xor_distance for atom %s: %s", atom_hex, exc)
|
|
131
|
-
is_self_closest = True
|
|
132
|
-
else:
|
|
133
|
-
try:
|
|
134
|
-
self_distance = xor_distance(atom_id, self.relay_public_key_bytes)
|
|
135
|
-
peer_distance = xor_distance(atom_id, closest_peer.public_key_bytes)
|
|
136
|
-
except Exception as exc:
|
|
137
|
-
node_logger.warning("Failed computing distance for atom %s: %s", atom_hex, exc)
|
|
138
|
-
is_self_closest = True
|
|
139
|
-
else:
|
|
140
|
-
is_self_closest = self_distance <= peer_distance
|
|
141
|
-
|
|
142
|
-
if is_self_closest:
|
|
143
|
-
node_logger.debug("Self is closest; indexing provider for atom %s", atom_hex)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
93
|
+
exc,
|
|
94
|
+
)
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
provider_ip, provider_port = self.incoming_socket.getsockname()[:2]
|
|
99
|
+
except Exception as exc:
|
|
100
|
+
node_logger.warning(
|
|
101
|
+
"Unable to determine provider address for atom %s: %s",
|
|
102
|
+
atom_hex,
|
|
103
|
+
exc,
|
|
104
|
+
)
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
provider_ip_bytes = socket.inet_aton(provider_ip)
|
|
109
|
+
provider_port_bytes = int(provider_port).to_bytes(2, "big", signed=False)
|
|
110
|
+
provider_key_bytes = self.relay_public_key_bytes
|
|
111
|
+
except Exception as exc:
|
|
112
|
+
node_logger.warning("Unable to encode provider info for %s: %s", atom_hex, exc)
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
provider_payload = provider_key_bytes + provider_ip_bytes + provider_port_bytes
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
closest_peer = self.peer_route.closest_peer_for_hash(atom_id)
|
|
119
|
+
except Exception as exc:
|
|
120
|
+
node_logger.warning("Peer lookup failed for atom %s: %s", atom_hex, exc)
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
is_self_closest = False
|
|
124
|
+
if closest_peer is None or closest_peer.address is None:
|
|
125
|
+
is_self_closest = True
|
|
126
|
+
else:
|
|
127
|
+
try:
|
|
128
|
+
from ...communication.util import xor_distance
|
|
129
|
+
except Exception as exc:
|
|
130
|
+
node_logger.warning("Failed to import xor_distance for atom %s: %s", atom_hex, exc)
|
|
131
|
+
is_self_closest = True
|
|
132
|
+
else:
|
|
133
|
+
try:
|
|
134
|
+
self_distance = xor_distance(atom_id, self.relay_public_key_bytes)
|
|
135
|
+
peer_distance = xor_distance(atom_id, closest_peer.public_key_bytes)
|
|
136
|
+
except Exception as exc:
|
|
137
|
+
node_logger.warning("Failed computing distance for atom %s: %s", atom_hex, exc)
|
|
138
|
+
is_self_closest = True
|
|
139
|
+
else:
|
|
140
|
+
is_self_closest = self_distance <= peer_distance
|
|
141
|
+
|
|
142
|
+
if is_self_closest:
|
|
143
|
+
node_logger.debug("Self is closest; indexing provider for atom %s", atom_hex)
|
|
144
|
+
provider_id = provider_id_for_payload(self, provider_payload)
|
|
145
|
+
self.storage_index[atom_id] = provider_id
|
|
146
|
+
return
|
|
147
|
+
|
|
148
|
+
target_addr = closest_peer.address
|
|
149
|
+
|
|
150
|
+
obj_req = ObjectRequest(
|
|
151
|
+
type=ObjectRequestType.OBJECT_PUT,
|
|
152
|
+
data=provider_payload,
|
|
153
|
+
atom_id=atom_id,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
message_body = obj_req.to_bytes()
|
|
157
|
+
|
|
157
158
|
message = Message(
|
|
158
159
|
topic=MessageTopic.OBJECT_REQUEST,
|
|
159
160
|
content=message_body,
|
|
@@ -161,18 +162,32 @@ def _network_set(self, atom: Atom) -> None:
|
|
|
161
162
|
)
|
|
162
163
|
message.encrypt(closest_peer.shared_key_bytes)
|
|
163
164
|
try:
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
target_addr[1],
|
|
165
|
+
queued = enqueue_outgoing(
|
|
166
|
+
self,
|
|
167
|
+
target_addr,
|
|
168
|
+
message=message,
|
|
169
|
+
difficulty=closest_peer.difficulty,
|
|
170
170
|
)
|
|
171
|
+
if queued:
|
|
172
|
+
node_logger.debug(
|
|
173
|
+
"Advertised atom %s to peer at %s:%s",
|
|
174
|
+
atom_hex,
|
|
175
|
+
target_addr[0],
|
|
176
|
+
target_addr[1],
|
|
177
|
+
)
|
|
178
|
+
else:
|
|
179
|
+
node_logger.debug(
|
|
180
|
+
"Dropped atom advertisement %s to peer at %s:%s",
|
|
181
|
+
atom_hex,
|
|
182
|
+
target_addr[0],
|
|
183
|
+
target_addr[1],
|
|
184
|
+
)
|
|
171
185
|
except Exception as exc:
|
|
172
186
|
node_logger.error(
|
|
173
187
|
"Failed to queue advertisement for atom %s to %s:%s: %s",
|
|
174
188
|
atom_hex,
|
|
175
|
-
target_addr[0],
|
|
176
|
-
target_addr[1],
|
|
177
|
-
exc,
|
|
178
|
-
)
|
|
189
|
+
target_addr[0],
|
|
190
|
+
target_addr[1],
|
|
191
|
+
exc,
|
|
192
|
+
)
|
|
193
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def provider_id_for_payload(node, payload: bytes) -> int:
|
|
8
|
+
"""Return the provider id for a payload, inserting if new."""
|
|
9
|
+
for idx, existing in enumerate(node.storage_providers):
|
|
10
|
+
if existing == payload:
|
|
11
|
+
return idx
|
|
12
|
+
node.storage_providers.append(payload)
|
|
13
|
+
return len(node.storage_providers) - 1
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def provider_payload_for_id(node, provider_id: int) -> Optional[bytes]:
|
|
18
|
+
"""Return the provider payload for a provider id, or None."""
|
|
19
|
+
if not isinstance(provider_id, int) or provider_id < 0:
|
|
20
|
+
return None
|
|
21
|
+
try:
|
|
22
|
+
return node.storage_providers[provider_id]
|
|
23
|
+
except IndexError:
|
|
24
|
+
return None
|
astreum/storage/setup.py
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def storage_setup(node: Any, config: dict) -> None:
|
|
7
|
-
"""Initialize hot/cold storage helpers on the node."""
|
|
8
|
-
|
|
9
|
-
node.logger.info("Setting up node storage")
|
|
10
|
-
|
|
11
|
-
node.hot_storage = {}
|
|
12
|
-
node.hot_storage_hits = {}
|
|
13
|
-
node.storage_index = {}
|
|
14
|
-
node.
|
|
15
|
-
node.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
config["
|
|
21
|
-
config["
|
|
22
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def storage_setup(node: Any, config: dict) -> None:
|
|
7
|
+
"""Initialize hot/cold storage helpers on the node."""
|
|
8
|
+
|
|
9
|
+
node.logger.info("Setting up node storage")
|
|
10
|
+
|
|
11
|
+
node.hot_storage = {}
|
|
12
|
+
node.hot_storage_hits = {}
|
|
13
|
+
node.storage_index = {}
|
|
14
|
+
node.storage_providers = []
|
|
15
|
+
node.hot_storage_size = 0
|
|
16
|
+
node.cold_storage_size = 0
|
|
17
|
+
|
|
18
|
+
node.logger.info(
|
|
19
|
+
"Storage ready (hot_limit=%s bytes, cold_limit=%s bytes, cold_path=%s)",
|
|
20
|
+
config["hot_storage_limit"],
|
|
21
|
+
config["cold_storage_limit"],
|
|
22
|
+
config["cold_storage_path"] or "disabled",
|
|
23
|
+
)
|