astreum 0.2.24__py3-none-any.whl → 0.2.26__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/crypto/wesolowski.py +2 -2
- astreum/models/block.py +185 -53
- astreum/models/merkle.py +6 -6
- astreum/models/transaction.py +3 -3
- {astreum-0.2.24.dist-info → astreum-0.2.26.dist-info}/METADATA +1 -1
- {astreum-0.2.24.dist-info → astreum-0.2.26.dist-info}/RECORD +9 -9
- {astreum-0.2.24.dist-info → astreum-0.2.26.dist-info}/WHEEL +0 -0
- {astreum-0.2.24.dist-info → astreum-0.2.26.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.24.dist-info → astreum-0.2.26.dist-info}/top_level.txt +0 -0
astreum/crypto/wesolowski.py
CHANGED
|
@@ -109,7 +109,7 @@ def deserialize(data: bytes, D: int) -> QuadraticForm:
|
|
|
109
109
|
|
|
110
110
|
# --- Public VDF API -----------------------------------------------------
|
|
111
111
|
|
|
112
|
-
def
|
|
112
|
+
def vdf_generate(
|
|
113
113
|
old_output: bytes,
|
|
114
114
|
T: int,
|
|
115
115
|
D: int
|
|
@@ -136,7 +136,7 @@ def generate(
|
|
|
136
136
|
return y_bytes, proof_bytes
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
def
|
|
139
|
+
def vdf_verify(
|
|
140
140
|
old_output: bytes,
|
|
141
141
|
new_output: bytes,
|
|
142
142
|
proof: bytes,
|
astreum/models/block.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from threading import Thread
|
|
3
4
|
from typing import List, Dict, Any, Optional, Union
|
|
4
5
|
|
|
6
|
+
from astreum.crypto.wesolowski import vdf_generate, vdf_verify
|
|
5
7
|
from astreum.models.account import Account
|
|
6
8
|
from astreum.models.accounts import Accounts
|
|
7
9
|
from astreum.models.patricia import PatriciaTrie
|
|
@@ -84,123 +86,162 @@ class Block:
|
|
|
84
86
|
return int.from_bytes(leaf_bytes, "big")
|
|
85
87
|
return leaf_bytes
|
|
86
88
|
|
|
87
|
-
def verify_block_signature(self) -> bool:
|
|
88
|
-
"""Verify the block's Ed25519 signature against its body root."""
|
|
89
|
-
pub = ed25519.Ed25519PublicKey.from_public_bytes(
|
|
90
|
-
self.get_field("validator_pk")
|
|
91
|
-
)
|
|
92
|
-
try:
|
|
93
|
-
pub.verify(self.get_signature(), self.get_body_hash())
|
|
94
|
-
return True
|
|
95
|
-
except Exception:
|
|
96
|
-
return False
|
|
97
|
-
|
|
98
89
|
@classmethod
|
|
99
90
|
def genesis(cls, validator_addr: bytes) -> "Block":
|
|
100
|
-
# 1
|
|
91
|
+
# 1. validator-stakes sub-trie
|
|
101
92
|
stake_trie = PatriciaTrie()
|
|
102
93
|
stake_trie.put(validator_addr, (1).to_bytes(32, "big"))
|
|
103
94
|
stake_root = stake_trie.root_hash
|
|
104
95
|
|
|
105
|
-
# 2
|
|
106
|
-
validator_acct = Account.create(balance=0, data=b"",
|
|
96
|
+
# 2. three Account bodies
|
|
97
|
+
validator_acct = Account.create(balance=0, data=b"", nonce=0)
|
|
107
98
|
treasury_acct = Account.create(balance=1, data=stake_root, nonce=0)
|
|
99
|
+
burn_acct = Account.create(balance=0, data=b"", nonce=0)
|
|
108
100
|
|
|
109
|
-
# 3
|
|
101
|
+
# 3. global Accounts structure
|
|
110
102
|
accts = Accounts()
|
|
111
103
|
accts.set_account(validator_addr, validator_acct)
|
|
112
104
|
accts.set_account(b"\x11" * 32, treasury_acct)
|
|
105
|
+
accts.set_account(b"\x00" * 32, burn_acct)
|
|
113
106
|
accounts_hash = accts.root_hash
|
|
114
107
|
|
|
115
|
-
# 4
|
|
108
|
+
# 4. constant body fields for genesis
|
|
116
109
|
body_kwargs = dict(
|
|
110
|
+
block_hash = b"",
|
|
117
111
|
number = 0,
|
|
118
112
|
prev_block_hash = b"\x00" * 32,
|
|
119
113
|
timestamp = 0,
|
|
114
|
+
block_time = 0,
|
|
120
115
|
accounts_hash = accounts_hash,
|
|
116
|
+
accounts = accts,
|
|
121
117
|
transactions_total_fees = 0,
|
|
122
|
-
transaction_limit =
|
|
118
|
+
transaction_limit = 1,
|
|
123
119
|
transactions_root_hash = b"\x00" * 32,
|
|
124
|
-
|
|
120
|
+
transactions_count = 0,
|
|
121
|
+
delay_difficulty = 1,
|
|
125
122
|
delay_output = b"",
|
|
126
123
|
delay_proof = b"",
|
|
127
124
|
validator_pk = validator_addr,
|
|
128
125
|
signature = b"",
|
|
129
126
|
)
|
|
130
127
|
|
|
131
|
-
# 5
|
|
128
|
+
# 5. build and return the block
|
|
132
129
|
return cls.create(**body_kwargs)
|
|
133
130
|
|
|
134
131
|
@classmethod
|
|
135
132
|
def build(
|
|
136
133
|
cls,
|
|
137
134
|
previous_block: "Block",
|
|
138
|
-
transactions:
|
|
135
|
+
transactions: List[Transaction],
|
|
139
136
|
*,
|
|
140
|
-
|
|
137
|
+
validator_sk,
|
|
141
138
|
natural_rate: float = 0.618,
|
|
142
139
|
) -> "Block":
|
|
143
140
|
BURN = b"\x00" * 32
|
|
144
141
|
|
|
145
|
-
# --- 0. create an empty block-in-progress, seeded with parent fields ----
|
|
146
142
|
blk = cls(
|
|
147
|
-
block_hash=b"",
|
|
143
|
+
block_hash=b"",
|
|
148
144
|
number=previous_block.number + 1,
|
|
149
145
|
prev_block_hash=previous_block.hash,
|
|
150
146
|
timestamp=previous_block.timestamp + 1,
|
|
151
147
|
accounts_hash=previous_block.accounts_hash,
|
|
152
148
|
transaction_limit=previous_block.transaction_limit,
|
|
153
149
|
transactions_count=0,
|
|
150
|
+
validator_pk=validator_sk.public_key().public_bytes(),
|
|
154
151
|
)
|
|
155
152
|
|
|
156
|
-
#
|
|
153
|
+
# ------------------ difficulty via natural_rate -----------------------
|
|
154
|
+
prev_bt = previous_block.block_time or 0
|
|
155
|
+
prev_diff = previous_block.delay_difficulty or 1
|
|
156
|
+
if prev_bt <= 1:
|
|
157
|
+
blk.delay_difficulty = max(1, int(prev_diff / natural_rate)) # increase
|
|
158
|
+
else:
|
|
159
|
+
blk.delay_difficulty = max(1, int(prev_diff * natural_rate)) # decrease
|
|
160
|
+
|
|
161
|
+
# ------------------ launch VDF in background --------------------------
|
|
162
|
+
vdf_result: dict[str, bytes] = {}
|
|
163
|
+
|
|
164
|
+
def _vdf_worker():
|
|
165
|
+
y, p = vdf_generate(previous_block.delay_output, blk.delay_difficulty, -4)
|
|
166
|
+
vdf_result["y"] = y
|
|
167
|
+
vdf_result["p"] = p
|
|
168
|
+
|
|
169
|
+
Thread(target=_vdf_worker, daemon=True).start()
|
|
170
|
+
|
|
171
|
+
# ------------------ process transactions -----------------------------
|
|
157
172
|
for tx in transactions:
|
|
158
173
|
try:
|
|
159
|
-
blk.apply_tx(tx)
|
|
174
|
+
blk.apply_tx(tx)
|
|
160
175
|
except ValueError:
|
|
161
|
-
break
|
|
176
|
+
break
|
|
162
177
|
|
|
163
|
-
#
|
|
178
|
+
# ------------------ split fees --------------------------------------
|
|
164
179
|
burn_amt = blk.total_fees // 2
|
|
165
180
|
reward_amt = blk.total_fees - burn_amt
|
|
181
|
+
|
|
182
|
+
def _credit(addr: bytes, amt: int):
|
|
183
|
+
acc = blk.accounts.get_account(addr) or Account.create(0, b"", 0)
|
|
184
|
+
blk.accounts.set_account(addr, Account.create(acc.balance() + amt, acc.data(), acc.nonce()))
|
|
185
|
+
|
|
166
186
|
if burn_amt:
|
|
167
|
-
|
|
168
|
-
BURN,
|
|
169
|
-
Account.create(
|
|
170
|
-
balance=(blk.accounts.get_account(BURN) or Account.create(0, b"", 0)).balance() + burn_amt,
|
|
171
|
-
data=b"",
|
|
172
|
-
nonce=0,
|
|
173
|
-
),
|
|
174
|
-
)
|
|
187
|
+
_credit(BURN, burn_amt)
|
|
175
188
|
if reward_amt:
|
|
176
|
-
blk.
|
|
177
|
-
validator_pk,
|
|
178
|
-
Account.create(
|
|
179
|
-
balance=(blk.accounts.get_account(validator_pk) or Account.create(0, b"", 0)).balance() + reward_amt,
|
|
180
|
-
data=b"",
|
|
181
|
-
nonce=0,
|
|
182
|
-
),
|
|
183
|
-
)
|
|
189
|
+
_credit(blk.validator_pk, reward_amt)
|
|
184
190
|
|
|
185
|
-
#
|
|
191
|
+
# ------------------ update tx limit with natural_rate ---------------
|
|
186
192
|
prev_limit = previous_block.transaction_limit
|
|
187
193
|
prev_tx_count = previous_block.transactions_count
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
grow_thr = prev_limit * natural_rate
|
|
195
|
+
shrink_thr = prev_tx_count * natural_rate
|
|
196
|
+
|
|
197
|
+
if prev_tx_count > grow_thr:
|
|
190
198
|
blk.transaction_limit = prev_tx_count
|
|
191
|
-
elif prev_tx_count <
|
|
199
|
+
elif prev_tx_count < shrink_thr:
|
|
192
200
|
blk.transaction_limit = max(1, int(prev_limit * natural_rate))
|
|
193
201
|
else:
|
|
194
202
|
blk.transaction_limit = prev_limit
|
|
195
203
|
|
|
196
|
-
#
|
|
204
|
+
# ------------------ wait for VDF ------------------------------------
|
|
205
|
+
while "y" not in vdf_result:
|
|
206
|
+
pass
|
|
207
|
+
blk.delay_output = vdf_result["y"]
|
|
208
|
+
blk.delay_proof = vdf_result["p"]
|
|
209
|
+
|
|
210
|
+
# ------------------ timing & roots ----------------------------------
|
|
211
|
+
blk.block_time = blk.timestamp - previous_block.timestamp
|
|
197
212
|
blk.accounts_hash = blk.accounts.root_hash
|
|
198
213
|
blk.transactions_root_hash = MerkleTree.from_leaves(blk.tx_hashes).root_hash
|
|
199
|
-
blk.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
214
|
+
blk.transactions_total_fees = blk.total_fees
|
|
215
|
+
|
|
216
|
+
# ------------------ build full body root ----------------------------
|
|
217
|
+
body_fields = {
|
|
218
|
+
"accounts_hash": blk.accounts_hash,
|
|
219
|
+
"block_time": blk.block_time,
|
|
220
|
+
"delay_difficulty": blk.delay_difficulty,
|
|
221
|
+
"delay_output": blk.delay_output,
|
|
222
|
+
"delay_proof": blk.delay_proof,
|
|
223
|
+
"number": blk.number,
|
|
224
|
+
"prev_block_hash": blk.prev_block_hash,
|
|
225
|
+
"timestamp": blk.timestamp,
|
|
226
|
+
"transaction_limit": blk.transaction_limit,
|
|
227
|
+
"transactions_count": blk.transactions_count,
|
|
228
|
+
"transactions_root_hash": blk.transactions_root_hash,
|
|
229
|
+
"transactions_total_fees": blk.transactions_total_fees,
|
|
230
|
+
"validator_pk": blk.validator_pk,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
leaves: List[bytes] = []
|
|
234
|
+
for k in sorted(body_fields):
|
|
235
|
+
v = body_fields[k]
|
|
236
|
+
if isinstance(v, bytes):
|
|
237
|
+
leaves.append(v)
|
|
238
|
+
else:
|
|
239
|
+
leaves.append(int(v).to_bytes((v.bit_length() + 7) // 8 or 1, "big"))
|
|
240
|
+
|
|
241
|
+
body_root = MerkleTree.from_leaves(leaves).root_hash
|
|
242
|
+
blk.body_tree = MerkleTree.from_leaves([body_root])
|
|
243
|
+
blk.signature = validator_sk.sign(body_root)
|
|
244
|
+
blk.hash = MerkleTree.from_leaves([body_root, blk.signature]).root_hash
|
|
204
245
|
|
|
205
246
|
return blk
|
|
206
247
|
|
|
@@ -298,3 +339,94 @@ class Block:
|
|
|
298
339
|
self.total_fees += fee
|
|
299
340
|
self.tx_hashes.append(tx.hash)
|
|
300
341
|
self.transactions_count += 1
|
|
342
|
+
|
|
343
|
+
def validate_block(self, remote_get_fn) -> bool:
|
|
344
|
+
NAT = 0.618
|
|
345
|
+
_i2b = lambda i: i.to_bytes((i.bit_length() + 7) // 8 or 1, "big")
|
|
346
|
+
|
|
347
|
+
# ---------- 1. block-hash & signature -----------------------------
|
|
348
|
+
blk_mt = MerkleTree(node_get=remote_get_fn, root_hash=self.hash)
|
|
349
|
+
body_root = blk_mt.get(0); sig = blk_mt.get(1)
|
|
350
|
+
ed25519.verify_signature(public_key=self.validator_pk, message=body_root, signature=sig)
|
|
351
|
+
|
|
352
|
+
# ---------- 2. rebuild body_root from fields ----------------------
|
|
353
|
+
f_names = (
|
|
354
|
+
"accounts_hash","block_time","delay_difficulty","delay_output","delay_proof",
|
|
355
|
+
"number","prev_block_hash","timestamp","transaction_limit",
|
|
356
|
+
"transactions_count","transactions_root_hash","transactions_total_fees",
|
|
357
|
+
"validator_pk",
|
|
358
|
+
)
|
|
359
|
+
leaves = [
|
|
360
|
+
v if isinstance(v := self.get_field(n), bytes) else _i2b(v)
|
|
361
|
+
for n in sorted(f_names)
|
|
362
|
+
]
|
|
363
|
+
if MerkleTree.from_leaves(leaves).root_hash != body_root:
|
|
364
|
+
raise ValueError("body root mismatch")
|
|
365
|
+
|
|
366
|
+
# ---------- 3. previous block header & VDF ------------------------
|
|
367
|
+
prev_mt = MerkleTree(node_get=remote_get_fn, root_hash=self.prev_block_hash)
|
|
368
|
+
prev_body_root, prev_sig = prev_mt.get(0), prev_mt.get(1)
|
|
369
|
+
prev_body_mt = MerkleTree(node_get=remote_get_fn, root_hash=prev_body_root)
|
|
370
|
+
prev_blk = Block(block_hash=self.prev_block_hash,
|
|
371
|
+
body_tree=prev_body_mt, signature=prev_sig)
|
|
372
|
+
prev_out = prev_blk.get_field("delay_output")
|
|
373
|
+
prev_diff = prev_blk.get_field("delay_difficulty")
|
|
374
|
+
prev_bt = prev_blk.get_field("block_time")
|
|
375
|
+
prev_limit = prev_blk.get_field("transaction_limit")
|
|
376
|
+
prev_cnt = prev_blk.get_field("transactions_count")
|
|
377
|
+
|
|
378
|
+
if not vdf_verify(prev_out, self.delay_output, self.delay_proof,
|
|
379
|
+
T=self.delay_difficulty, D=-4):
|
|
380
|
+
raise ValueError("bad VDF proof")
|
|
381
|
+
|
|
382
|
+
# ---------- 4. replay all txs -------------------------------------
|
|
383
|
+
accs = Accounts(root_hash=prev_blk.get_field("accounts_hash"),
|
|
384
|
+
node_get=remote_get_fn)
|
|
385
|
+
tx_mt = MerkleTree(node_get=remote_get_fn,
|
|
386
|
+
root_hash=self.transactions_root_hash)
|
|
387
|
+
if tx_mt.leaf_count() != self.transactions_count:
|
|
388
|
+
raise ValueError("transactions_count mismatch")
|
|
389
|
+
|
|
390
|
+
dummy = Block(block_hash=b"", accounts=accs,
|
|
391
|
+
accounts_hash=accs.root_hash,
|
|
392
|
+
transaction_limit=prev_limit)
|
|
393
|
+
for i in range(self.transactions_count):
|
|
394
|
+
h = tx_mt.get(i)
|
|
395
|
+
tm = MerkleTree(node_get=remote_get_fn, root_hash=h)
|
|
396
|
+
tx = Transaction(h, tree=tm, node_get=remote_get_fn)
|
|
397
|
+
dummy.apply_tx(tx)
|
|
398
|
+
|
|
399
|
+
# fee split identical to build()
|
|
400
|
+
burn = dummy.total_fees // 2
|
|
401
|
+
rew = dummy.total_fees - burn
|
|
402
|
+
if burn:
|
|
403
|
+
dummy.accounts.set_account(
|
|
404
|
+
b"\x00"*32,
|
|
405
|
+
Account.create(burn, b"", 0)
|
|
406
|
+
)
|
|
407
|
+
if rew:
|
|
408
|
+
v_acct = dummy.accounts.get_account(self.validator_pk) or Account.create(0,b"",0)
|
|
409
|
+
dummy.accounts.set_account(
|
|
410
|
+
self.validator_pk,
|
|
411
|
+
Account.create(v_acct.balance()+rew, v_acct.data(), v_acct.nonce())
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
if dummy.accounts.root_hash != self.accounts_hash:
|
|
415
|
+
raise ValueError("accounts_hash mismatch")
|
|
416
|
+
|
|
417
|
+
# ---------- 5. natural-rate rules --------------------------------
|
|
418
|
+
grow_thr = prev_limit * NAT
|
|
419
|
+
shrink_thr = prev_cnt * NAT
|
|
420
|
+
expect_lim = prev_cnt if prev_cnt > grow_thr \
|
|
421
|
+
else max(1, int(prev_limit * NAT)) if prev_cnt < shrink_thr \
|
|
422
|
+
else prev_limit
|
|
423
|
+
if self.transaction_limit != expect_lim:
|
|
424
|
+
raise ValueError("tx-limit rule")
|
|
425
|
+
|
|
426
|
+
expect_diff = max(1, int(prev_diff / NAT)) if prev_bt <= 1 \
|
|
427
|
+
else max(1, int(prev_diff * NAT))
|
|
428
|
+
if self.delay_difficulty != expect_diff:
|
|
429
|
+
raise ValueError("difficulty rule")
|
|
430
|
+
|
|
431
|
+
return True
|
|
432
|
+
|
astreum/models/merkle.py
CHANGED
|
@@ -41,11 +41,11 @@ class MerkleNode:
|
|
|
41
41
|
class MerkleTree:
|
|
42
42
|
def __init__(
|
|
43
43
|
self,
|
|
44
|
-
|
|
44
|
+
global_get_fn: Callable[[bytes], Optional[bytes]],
|
|
45
45
|
root_hash: Optional[bytes] = None,
|
|
46
46
|
height: Optional[int] = None,
|
|
47
47
|
) -> None:
|
|
48
|
-
self.
|
|
48
|
+
self._global_get_fn = global_get_fn
|
|
49
49
|
self.nodes: Dict[bytes, MerkleNode] = {}
|
|
50
50
|
self.root_hash = root_hash
|
|
51
51
|
self._height: Optional[int] = height
|
|
@@ -54,13 +54,13 @@ class MerkleTree:
|
|
|
54
54
|
def from_leaves(
|
|
55
55
|
cls,
|
|
56
56
|
leaves: List[bytes],
|
|
57
|
-
|
|
57
|
+
global_get_fn: Callable[[bytes], Optional[bytes]] | None = None,
|
|
58
58
|
) -> "MerkleTree":
|
|
59
59
|
if not leaves:
|
|
60
60
|
raise ValueError("must supply at least one leaf")
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
tree = cls(
|
|
62
|
+
global_get_fn = global_get_fn or (lambda _h: None)
|
|
63
|
+
tree = cls(global_get_fn=global_get_fn)
|
|
64
64
|
|
|
65
65
|
# Step 1 – create leaf nodes list[bytes]
|
|
66
66
|
level_hashes: List[bytes] = []
|
|
@@ -97,7 +97,7 @@ class MerkleTree:
|
|
|
97
97
|
return None
|
|
98
98
|
node = self.nodes.get(h)
|
|
99
99
|
if node is None:
|
|
100
|
-
raw = self.
|
|
100
|
+
raw = self._global_get_fn(h)
|
|
101
101
|
if raw is None:
|
|
102
102
|
return None
|
|
103
103
|
node = MerkleNode.from_bytes(raw)
|
astreum/models/transaction.py
CHANGED
|
@@ -27,14 +27,14 @@ class Transaction:
|
|
|
27
27
|
tx_hash: bytes,
|
|
28
28
|
*,
|
|
29
29
|
tree: Optional[MerkleTree] = None,
|
|
30
|
-
|
|
30
|
+
global_get_fn: Optional[Callable[[bytes], Optional[bytes]]] = None,
|
|
31
31
|
) -> None:
|
|
32
32
|
self._hash = tx_hash
|
|
33
33
|
self._tree = tree
|
|
34
34
|
self._field_cache: Dict[str, Union[int, bytes]] = {}
|
|
35
35
|
|
|
36
|
-
if self._tree and
|
|
37
|
-
self._tree.
|
|
36
|
+
if self._tree and global_get_fn:
|
|
37
|
+
self._tree.global_get_fn = global_get_fn
|
|
38
38
|
|
|
39
39
|
@classmethod
|
|
40
40
|
def create(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astreum
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.26
|
|
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
|
|
@@ -4,7 +4,7 @@ astreum/node.py,sha256=dPloCXuDyIn3-KDqxlgl3jxsonJlFMLi_quwJRsoLC8,46259
|
|
|
4
4
|
astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
|
|
6
6
|
astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
|
|
7
|
-
astreum/crypto/wesolowski.py,sha256=
|
|
7
|
+
astreum/crypto/wesolowski.py,sha256=SUgGXW3Id07dJtWzDcs4dluIhjqbRWQ8YWjn_mK78AQ,4092
|
|
8
8
|
astreum/crypto/x25519.py,sha256=i29v4BmwKRcbz9E7NKqFDQyxzFtJUqN0St9jd7GS1uA,1137
|
|
9
9
|
astreum/lispeum/__init__.py,sha256=K-NDzIjtIsXzC9X7lnYvlvIaVxjFcY7WNsgLIE3DH3U,58
|
|
10
10
|
astreum/lispeum/parser.py,sha256=jQRzZYvBuSg8t_bxsbt1-WcHaR_LPveHNX7Qlxhaw-M,1165
|
|
@@ -12,12 +12,12 @@ astreum/lispeum/tokenizer.py,sha256=J-I7MEd0r2ZoVqxvRPlu-Afe2ZdM0tKXXhf1R4SxYTo,
|
|
|
12
12
|
astreum/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
astreum/models/account.py,sha256=sHujGSwtV13rvOGJ5LZXuMrJ4F9XUdvyuWKz-zJ9lkE,2986
|
|
14
14
|
astreum/models/accounts.py,sha256=aFSEWlq6zRf65-KGAdNGqEJyNVY3fpKhx8y1vU6sgSc,1164
|
|
15
|
-
astreum/models/block.py,sha256
|
|
16
|
-
astreum/models/merkle.py,sha256=
|
|
15
|
+
astreum/models/block.py,sha256=-5j7uO0woVtNi0h52__e7AxpDQSVhzKUhr6Qc-2xZsE,17870
|
|
16
|
+
astreum/models/merkle.py,sha256=lvWJa9nmrBL0n_2h_uNqpB_9a5s5Hn1FceRLx0IZIVQ,6778
|
|
17
17
|
astreum/models/patricia.py,sha256=ohmXrcaz7Ae561tyC4u4iPOkQPkKr8N0IWJek4upFIg,13392
|
|
18
|
-
astreum/models/transaction.py,sha256=
|
|
19
|
-
astreum-0.2.
|
|
20
|
-
astreum-0.2.
|
|
21
|
-
astreum-0.2.
|
|
22
|
-
astreum-0.2.
|
|
23
|
-
astreum-0.2.
|
|
18
|
+
astreum/models/transaction.py,sha256=MkLL5YX18kIf9-O4LBaZ4eWjkXDAaYIrDcDehbDZoqg,3038
|
|
19
|
+
astreum-0.2.26.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
|
|
20
|
+
astreum-0.2.26.dist-info/METADATA,sha256=fUG5PepefY7Cjfp5Gj5GwtbYF369bARQAcl0A4OJiQ0,5478
|
|
21
|
+
astreum-0.2.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
22
|
+
astreum-0.2.26.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
|
|
23
|
+
astreum-0.2.26.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|