astreum 0.2.27__tar.gz → 0.2.28__tar.gz
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-0.2.27/src/astreum.egg-info → astreum-0.2.28}/PKG-INFO +1 -1
- {astreum-0.2.27 → astreum-0.2.28}/pyproject.toml +1 -1
- astreum-0.2.28/src/astreum/lispeum/environment.py +40 -0
- astreum-0.2.28/src/astreum/lispeum/expression.py +86 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/node.py +12 -183
- astreum-0.2.28/src/astreum/storage/__init__.py +0 -0
- astreum-0.2.28/src/astreum/storage/object.py +68 -0
- astreum-0.2.28/src/astreum/storage/setup.py +16 -0
- {astreum-0.2.27 → astreum-0.2.28/src/astreum.egg-info}/PKG-INFO +1 -1
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum.egg-info/SOURCES.txt +5 -0
- {astreum-0.2.27 → astreum-0.2.28}/LICENSE +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/README.md +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/setup.cfg +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/__init__.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/crypto/__init__.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/crypto/ed25519.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/crypto/quadratic_form.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/crypto/wesolowski.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/crypto/x25519.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/format.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/lispeum/__init__.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/lispeum/parser.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/lispeum/tokenizer.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/__init__.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/account.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/accounts.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/block.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/merkle.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/message.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/patricia.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum/models/transaction.py +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum.egg-info/dependency_links.txt +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum.egg-info/requires.txt +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/src/astreum.egg-info/top_level.txt +0 -0
- {astreum-0.2.27 → astreum-0.2.28}/tests/test_node_machine.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.28
|
|
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
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from typing import Dict, Optional
|
|
2
|
+
import uuid
|
|
3
|
+
|
|
4
|
+
from astreum.lispeum.expression import Expr
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Env:
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
data: Optional[Dict[str, Expr]] = None,
|
|
11
|
+
parent_id: Optional[uuid.UUID] = None,
|
|
12
|
+
max_exprs: Optional[int] = 8,
|
|
13
|
+
):
|
|
14
|
+
self.data: Dict[str, Expr] = data if data is not None else {}
|
|
15
|
+
self.parent_id: Optional[uuid.UUID] = parent_id
|
|
16
|
+
self.max_exprs: Optional[int] = max_exprs
|
|
17
|
+
|
|
18
|
+
def put(self, name: str, value: Expr) -> None:
|
|
19
|
+
if (
|
|
20
|
+
self.max_exprs is not None
|
|
21
|
+
and name not in self.data
|
|
22
|
+
and len(self.data) >= self.max_exprs
|
|
23
|
+
):
|
|
24
|
+
raise RuntimeError(
|
|
25
|
+
f"environment full: {len(self.data)} ≥ max_exprs={self.max_exprs}"
|
|
26
|
+
)
|
|
27
|
+
self.data[name] = value
|
|
28
|
+
|
|
29
|
+
def get(self, name: str) -> Optional[Expr]:
|
|
30
|
+
return self.data.get(name)
|
|
31
|
+
|
|
32
|
+
def pop(self, name: str) -> Optional[Expr]:
|
|
33
|
+
return self.data.pop(name, None)
|
|
34
|
+
|
|
35
|
+
def __repr__(self) -> str:
|
|
36
|
+
return (
|
|
37
|
+
f"Env(size={len(self.data)}, "
|
|
38
|
+
f"max_exprs={self.max_exprs}, "
|
|
39
|
+
f"parent_id={self.parent_id})"
|
|
40
|
+
)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Expr:
|
|
6
|
+
class ListExpr:
|
|
7
|
+
def __init__(self, elements: List['Expr']):
|
|
8
|
+
self.elements = elements
|
|
9
|
+
|
|
10
|
+
def __eq__(self, other):
|
|
11
|
+
if not isinstance(other, Expr.ListExpr):
|
|
12
|
+
return NotImplemented
|
|
13
|
+
return self.elements == other.elements
|
|
14
|
+
|
|
15
|
+
def __ne__(self, other):
|
|
16
|
+
return not self.__eq__(other)
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def value(self):
|
|
20
|
+
inner = " ".join(str(e) for e in self.elements)
|
|
21
|
+
return f"({inner})"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def __repr__(self):
|
|
25
|
+
if not self.elements:
|
|
26
|
+
return "()"
|
|
27
|
+
|
|
28
|
+
inner = " ".join(str(e) for e in self.elements)
|
|
29
|
+
return f"({inner})"
|
|
30
|
+
|
|
31
|
+
def __iter__(self):
|
|
32
|
+
return iter(self.elements)
|
|
33
|
+
|
|
34
|
+
def __getitem__(self, index: Union[int, slice]):
|
|
35
|
+
return self.elements[index]
|
|
36
|
+
|
|
37
|
+
def __len__(self):
|
|
38
|
+
return len(self.elements)
|
|
39
|
+
|
|
40
|
+
class Symbol:
|
|
41
|
+
def __init__(self, value: str):
|
|
42
|
+
self.value = value
|
|
43
|
+
|
|
44
|
+
def __repr__(self):
|
|
45
|
+
return self.value
|
|
46
|
+
|
|
47
|
+
class Integer:
|
|
48
|
+
def __init__(self, value: int):
|
|
49
|
+
self.value = value
|
|
50
|
+
|
|
51
|
+
def __repr__(self):
|
|
52
|
+
return str(self.value)
|
|
53
|
+
|
|
54
|
+
class String:
|
|
55
|
+
def __init__(self, value: str):
|
|
56
|
+
self.value = value
|
|
57
|
+
|
|
58
|
+
def __repr__(self):
|
|
59
|
+
return f'"{self.value}"'
|
|
60
|
+
|
|
61
|
+
class Boolean:
|
|
62
|
+
def __init__(self, value: bool):
|
|
63
|
+
self.value = value
|
|
64
|
+
|
|
65
|
+
def __repr__(self):
|
|
66
|
+
return "true" if self.value else "false"
|
|
67
|
+
|
|
68
|
+
class Function:
|
|
69
|
+
def __init__(self, params: List[str], body: 'Expr'):
|
|
70
|
+
self.params = params
|
|
71
|
+
self.body = body
|
|
72
|
+
|
|
73
|
+
def __repr__(self):
|
|
74
|
+
params_str = " ".join(self.params)
|
|
75
|
+
body_str = str(self.body)
|
|
76
|
+
return f"(fn ({params_str}) {body_str})"
|
|
77
|
+
|
|
78
|
+
class Error:
|
|
79
|
+
def __init__(self, message: str, origin: Optional['Expr'] = None):
|
|
80
|
+
self.message = message
|
|
81
|
+
self.origin = origin
|
|
82
|
+
|
|
83
|
+
def __repr__(self):
|
|
84
|
+
if self.origin is None:
|
|
85
|
+
return f'(error "{self.message}")'
|
|
86
|
+
return f'(error "{self.message}" in {self.origin})'
|
|
@@ -7,60 +7,21 @@ from typing import Tuple, Dict, Union, Optional, List
|
|
|
7
7
|
from datetime import datetime, timedelta, timezone
|
|
8
8
|
import uuid
|
|
9
9
|
|
|
10
|
+
from astreum.lispeum.environment import Env
|
|
11
|
+
from astreum.lispeum.expression import Expr
|
|
12
|
+
from astreum.storage.object import ObjectRequest, ObjectRequestType, ObjectResponse, ObjectResponseType
|
|
13
|
+
from astreum.storage.setup import storage_setup
|
|
14
|
+
|
|
10
15
|
from .models.transaction import Transaction
|
|
11
16
|
from .format import encode, decode
|
|
12
17
|
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
|
|
13
18
|
from cryptography.hazmat.primitives import serialization
|
|
14
19
|
from .crypto import ed25519, x25519
|
|
15
|
-
from enum import IntEnum
|
|
16
20
|
import blake3
|
|
17
21
|
import struct
|
|
18
22
|
from .models.message import Message, MessageTopic
|
|
19
23
|
|
|
20
|
-
class ObjectRequestType(IntEnum):
|
|
21
|
-
OBJECT_GET = 0
|
|
22
|
-
OBJECT_PUT = 1
|
|
23
|
-
|
|
24
|
-
class ObjectRequest:
|
|
25
|
-
type: ObjectRequestType
|
|
26
|
-
data: bytes
|
|
27
|
-
hash: bytes
|
|
28
|
-
|
|
29
|
-
def __init__(self, type: ObjectRequestType, data: bytes, hash: bytes = None):
|
|
30
|
-
self.type = type
|
|
31
|
-
self.data = data
|
|
32
|
-
self.hash = hash
|
|
33
|
-
|
|
34
|
-
def to_bytes(self):
|
|
35
|
-
return encode([self.type.value, self.data, self.hash])
|
|
36
|
-
|
|
37
|
-
@classmethod
|
|
38
|
-
def from_bytes(cls, data: bytes):
|
|
39
|
-
type_val, data_val, hash_val = decode(data)
|
|
40
|
-
return cls(type=ObjectRequestType(type_val[0]), data=data_val, hash=hash_val)
|
|
41
|
-
|
|
42
|
-
class ObjectResponseType(IntEnum):
|
|
43
|
-
OBJECT_FOUND = 0
|
|
44
|
-
OBJECT_PROVIDER = 1
|
|
45
|
-
OBJECT_NEAREST_PEER = 2
|
|
46
|
-
|
|
47
|
-
class ObjectResponse:
|
|
48
|
-
type: ObjectResponseType
|
|
49
|
-
data: bytes
|
|
50
|
-
hash: bytes
|
|
51
|
-
|
|
52
|
-
def __init__(self, type: ObjectResponseType, data: bytes, hash: bytes = None):
|
|
53
|
-
self.type = type
|
|
54
|
-
self.data = data
|
|
55
|
-
self.hash = hash
|
|
56
|
-
|
|
57
|
-
def to_bytes(self):
|
|
58
|
-
return encode([self.type.value, self.data, self.hash])
|
|
59
24
|
|
|
60
|
-
@classmethod
|
|
61
|
-
def from_bytes(cls, data: bytes):
|
|
62
|
-
type_val, data_val, hash_val = decode(data)
|
|
63
|
-
return cls(type=ObjectResponseType(type_val[0]), data=data_val, hash=hash_val)
|
|
64
25
|
|
|
65
26
|
class Peer:
|
|
66
27
|
shared_key: bytes
|
|
@@ -109,135 +70,18 @@ def decode_ip_address(data: bytes) -> tuple[str, int]:
|
|
|
109
70
|
raise ValueError("Invalid address byte format")
|
|
110
71
|
return ip, port
|
|
111
72
|
|
|
112
|
-
# =========
|
|
113
|
-
# MACHINE
|
|
114
|
-
# =========
|
|
115
|
-
|
|
116
|
-
class Expr:
|
|
117
|
-
class ListExpr:
|
|
118
|
-
def __init__(self, elements: List['Expr']):
|
|
119
|
-
self.elements = elements
|
|
120
|
-
|
|
121
|
-
def __eq__(self, other):
|
|
122
|
-
if not isinstance(other, Expr.ListExpr):
|
|
123
|
-
return NotImplemented
|
|
124
|
-
return self.elements == other.elements
|
|
125
|
-
|
|
126
|
-
def __ne__(self, other):
|
|
127
|
-
return not self.__eq__(other)
|
|
128
|
-
|
|
129
|
-
@property
|
|
130
|
-
def value(self):
|
|
131
|
-
inner = " ".join(str(e) for e in self.elements)
|
|
132
|
-
return f"({inner})"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def __repr__(self):
|
|
136
|
-
if not self.elements:
|
|
137
|
-
return "()"
|
|
138
|
-
|
|
139
|
-
inner = " ".join(str(e) for e in self.elements)
|
|
140
|
-
return f"({inner})"
|
|
141
|
-
|
|
142
|
-
def __iter__(self):
|
|
143
|
-
return iter(self.elements)
|
|
144
|
-
|
|
145
|
-
def __getitem__(self, index: Union[int, slice]):
|
|
146
|
-
return self.elements[index]
|
|
147
|
-
|
|
148
|
-
def __len__(self):
|
|
149
|
-
return len(self.elements)
|
|
150
|
-
|
|
151
|
-
class Symbol:
|
|
152
|
-
def __init__(self, value: str):
|
|
153
|
-
self.value = value
|
|
154
|
-
|
|
155
|
-
def __repr__(self):
|
|
156
|
-
return self.value
|
|
157
|
-
|
|
158
|
-
class Integer:
|
|
159
|
-
def __init__(self, value: int):
|
|
160
|
-
self.value = value
|
|
161
|
-
|
|
162
|
-
def __repr__(self):
|
|
163
|
-
return str(self.value)
|
|
164
|
-
|
|
165
|
-
class String:
|
|
166
|
-
def __init__(self, value: str):
|
|
167
|
-
self.value = value
|
|
168
|
-
|
|
169
|
-
def __repr__(self):
|
|
170
|
-
return f'"{self.value}"'
|
|
171
|
-
|
|
172
|
-
class Boolean:
|
|
173
|
-
def __init__(self, value: bool):
|
|
174
|
-
self.value = value
|
|
175
|
-
|
|
176
|
-
def __repr__(self):
|
|
177
|
-
return "true" if self.value else "false"
|
|
178
|
-
|
|
179
|
-
class Function:
|
|
180
|
-
def __init__(self, params: List[str], body: 'Expr'):
|
|
181
|
-
self.params = params
|
|
182
|
-
self.body = body
|
|
183
|
-
|
|
184
|
-
def __repr__(self):
|
|
185
|
-
params_str = " ".join(self.params)
|
|
186
|
-
body_str = str(self.body)
|
|
187
|
-
return f"(fn ({params_str}) {body_str})"
|
|
188
|
-
|
|
189
|
-
class Error:
|
|
190
|
-
def __init__(self, message: str, origin: Optional['Expr'] = None):
|
|
191
|
-
self.message = message
|
|
192
|
-
self.origin = origin
|
|
193
|
-
|
|
194
|
-
def __repr__(self):
|
|
195
|
-
if self.origin is None:
|
|
196
|
-
return f'(error "{self.message}")'
|
|
197
|
-
return f'(error "{self.message}" in {self.origin})'
|
|
198
|
-
|
|
199
|
-
class Env:
|
|
200
|
-
def __init__(
|
|
201
|
-
self,
|
|
202
|
-
data: Optional[Dict[str, Expr]] = None,
|
|
203
|
-
parent_id: Optional[uuid.UUID] = None,
|
|
204
|
-
max_exprs: Optional[int] = 8,
|
|
205
|
-
):
|
|
206
|
-
self.data: Dict[str, Expr] = data if data is not None else {}
|
|
207
|
-
self.parent_id: Optional[uuid.UUID] = parent_id
|
|
208
|
-
self.max_exprs: Optional[int] = max_exprs
|
|
209
|
-
|
|
210
|
-
def put(self, name: str, value: Expr) -> None:
|
|
211
|
-
if (
|
|
212
|
-
self.max_exprs is not None
|
|
213
|
-
and name not in self.data
|
|
214
|
-
and len(self.data) >= self.max_exprs
|
|
215
|
-
):
|
|
216
|
-
raise RuntimeError(
|
|
217
|
-
f"environment full: {len(self.data)} ≥ max_exprs={self.max_exprs}"
|
|
218
|
-
)
|
|
219
|
-
self.data[name] = value
|
|
220
|
-
|
|
221
|
-
def get(self, name: str) -> Optional[Expr]:
|
|
222
|
-
return self.data.get(name)
|
|
223
|
-
|
|
224
|
-
def pop(self, name: str) -> Optional[Expr]:
|
|
225
|
-
return self.data.pop(name, None)
|
|
226
|
-
|
|
227
|
-
def __repr__(self) -> str:
|
|
228
|
-
return (
|
|
229
|
-
f"Env(size={len(self.data)}, "
|
|
230
|
-
f"max_exprs={self.max_exprs}, "
|
|
231
|
-
f"parent_id={self.parent_id})"
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
|
|
235
73
|
class Node:
|
|
236
74
|
def __init__(self, config: dict = {}):
|
|
237
75
|
self._machine_setup()
|
|
238
76
|
machine_only = bool(config.get('machine-only', True))
|
|
239
77
|
if not machine_only:
|
|
240
|
-
|
|
78
|
+
(
|
|
79
|
+
self.storage_path,
|
|
80
|
+
self.memory_storage,
|
|
81
|
+
self.storage_get_relay_timeout,
|
|
82
|
+
self.storage_index
|
|
83
|
+
) = storage_setup(config)
|
|
84
|
+
|
|
241
85
|
self._relay_setup(config=config)
|
|
242
86
|
self._validation_setup(config=config)
|
|
243
87
|
|
|
@@ -250,21 +94,6 @@ class Node:
|
|
|
250
94
|
def _create_block(self):
|
|
251
95
|
pass
|
|
252
96
|
|
|
253
|
-
# STORAGE METHODS
|
|
254
|
-
def _storage_setup(self, config: dict):
|
|
255
|
-
storage_path_str = config.get('storage_path')
|
|
256
|
-
if storage_path_str is None:
|
|
257
|
-
self.storage_path = None
|
|
258
|
-
self.memory_storage = {}
|
|
259
|
-
else:
|
|
260
|
-
self.storage_path = Path(storage_path_str)
|
|
261
|
-
self.storage_path.mkdir(parents=True, exist_ok=True)
|
|
262
|
-
self.memory_storage = None
|
|
263
|
-
|
|
264
|
-
self.storage_get_relay_timeout = config.get('storage_get_relay_timeout', 5)
|
|
265
|
-
# STORAGE INDEX: (object_hash, encoded (provider_public_key, provider_address))
|
|
266
|
-
self.storage_index = Dict[bytes, bytes]
|
|
267
|
-
|
|
268
97
|
def _relay_setup(self, config: dict):
|
|
269
98
|
self.use_ipv6 = config.get('use_ipv6', False)
|
|
270
99
|
incoming_port = config.get('incoming_port', 7373)
|
|
File without changes
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
|
|
3
|
+
class ObjectRequestType(IntEnum):
|
|
4
|
+
OBJECT_GET = 0
|
|
5
|
+
OBJECT_PUT = 1
|
|
6
|
+
|
|
7
|
+
class ObjectRequest:
|
|
8
|
+
type: ObjectRequestType
|
|
9
|
+
data: bytes
|
|
10
|
+
hash: bytes
|
|
11
|
+
|
|
12
|
+
def __init__(self, type: ObjectRequestType, data: bytes, hash: bytes = None):
|
|
13
|
+
self.type = type
|
|
14
|
+
self.data = data
|
|
15
|
+
self.hash = hash
|
|
16
|
+
|
|
17
|
+
def to_bytes(self):
|
|
18
|
+
return [self.type.value] + self.hash + self.data
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_bytes(cls, data: bytes) -> "ObjectRequest":
|
|
22
|
+
# need at least 1 byte for type + 32 bytes for hash
|
|
23
|
+
if len(data) < 1 + 32:
|
|
24
|
+
raise ValueError(f"Too short for ObjectRequest ({len(data)} bytes)")
|
|
25
|
+
|
|
26
|
+
type_val = data[0]
|
|
27
|
+
try:
|
|
28
|
+
req_type = ObjectRequestType(type_val)
|
|
29
|
+
except ValueError:
|
|
30
|
+
raise ValueError(f"Unknown ObjectRequestType: {type_val!r}")
|
|
31
|
+
|
|
32
|
+
hash_bytes = data[1:33]
|
|
33
|
+
payload = data[33:]
|
|
34
|
+
return cls(req_type, payload, hash_bytes)
|
|
35
|
+
|
|
36
|
+
class ObjectResponseType(IntEnum):
|
|
37
|
+
OBJECT_FOUND = 0
|
|
38
|
+
OBJECT_PROVIDER = 1
|
|
39
|
+
OBJECT_NEAREST_PEER = 2
|
|
40
|
+
|
|
41
|
+
class ObjectResponse:
|
|
42
|
+
type: ObjectResponseType
|
|
43
|
+
data: bytes
|
|
44
|
+
hash: bytes
|
|
45
|
+
|
|
46
|
+
def __init__(self, type: ObjectResponseType, data: bytes, hash: bytes = None):
|
|
47
|
+
self.type = type
|
|
48
|
+
self.data = data
|
|
49
|
+
self.hash = hash
|
|
50
|
+
|
|
51
|
+
def to_bytes(self):
|
|
52
|
+
return [self.type.value] + self.hash + self.data
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def from_bytes(cls, data: bytes) -> "ObjectResponse":
|
|
56
|
+
# need at least 1 byte for type + 32 bytes for hash
|
|
57
|
+
if len(data) < 1 + 32:
|
|
58
|
+
raise ValueError(f"Too short to be a valid ObjectResponse ({len(data)} bytes)")
|
|
59
|
+
|
|
60
|
+
type_val = data[0]
|
|
61
|
+
try:
|
|
62
|
+
resp_type = ObjectResponseType(type_val)
|
|
63
|
+
except ValueError:
|
|
64
|
+
raise ValueError(f"Unknown ObjectResponseType: {type_val}")
|
|
65
|
+
|
|
66
|
+
hash_bytes = data[1:33]
|
|
67
|
+
payload = data[33:]
|
|
68
|
+
return cls(resp_type, payload, hash_bytes)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional, Dict, Tuple, Any
|
|
3
|
+
|
|
4
|
+
def storage_setup(config: dict
|
|
5
|
+
) -> Tuple[Optional[Path], Dict[bytes, Any], int, Dict[bytes, bytes]]:
|
|
6
|
+
storage_path_str = config.get('storage_path')
|
|
7
|
+
if storage_path_str is None:
|
|
8
|
+
storage_path, memory_storage = None, {}
|
|
9
|
+
else:
|
|
10
|
+
storage_path = Path(storage_path_str)
|
|
11
|
+
storage_path.mkdir(parents=True, exist_ok=True)
|
|
12
|
+
memory_storage = None
|
|
13
|
+
|
|
14
|
+
timeout = config.get('storage_get_relay_timeout', 5)
|
|
15
|
+
storage_index: Dict[bytes, bytes] = {}
|
|
16
|
+
return storage_path, memory_storage, timeout, storage_index
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.28
|
|
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
|
|
@@ -15,6 +15,8 @@ src/astreum/crypto/quadratic_form.py
|
|
|
15
15
|
src/astreum/crypto/wesolowski.py
|
|
16
16
|
src/astreum/crypto/x25519.py
|
|
17
17
|
src/astreum/lispeum/__init__.py
|
|
18
|
+
src/astreum/lispeum/environment.py
|
|
19
|
+
src/astreum/lispeum/expression.py
|
|
18
20
|
src/astreum/lispeum/parser.py
|
|
19
21
|
src/astreum/lispeum/tokenizer.py
|
|
20
22
|
src/astreum/models/__init__.py
|
|
@@ -25,4 +27,7 @@ src/astreum/models/merkle.py
|
|
|
25
27
|
src/astreum/models/message.py
|
|
26
28
|
src/astreum/models/patricia.py
|
|
27
29
|
src/astreum/models/transaction.py
|
|
30
|
+
src/astreum/storage/__init__.py
|
|
31
|
+
src/astreum/storage/object.py
|
|
32
|
+
src/astreum/storage/setup.py
|
|
28
33
|
tests/test_node_machine.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|