astreum 0.2.24__py3-none-any.whl → 0.2.25__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.

@@ -109,7 +109,7 @@ def deserialize(data: bytes, D: int) -> QuadraticForm:
109
109
 
110
110
  # --- Public VDF API -----------------------------------------------------
111
111
 
112
- def generate(
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 verify(
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
5
7
  from astreum.models.account import Account
6
8
  from astreum.models.accounts import Accounts
7
9
  from astreum.models.patricia import PatriciaTrie
@@ -135,72 +137,117 @@ class Block:
135
137
  def build(
136
138
  cls,
137
139
  previous_block: "Block",
138
- transactions: list[Transaction],
140
+ transactions: List[Transaction],
139
141
  *,
140
- validator_pk: bytes,
142
+ validator_sk, # private key for signing
141
143
  natural_rate: float = 0.618,
142
144
  ) -> "Block":
145
+ TREASURY = b"\x11" * 32
143
146
  BURN = b"\x00" * 32
144
147
 
145
- # --- 0. create an empty block-in-progress, seeded with parent fields ----
146
148
  blk = cls(
147
- block_hash=b"", # placeholder; set at the end
149
+ block_hash=b"",
148
150
  number=previous_block.number + 1,
149
151
  prev_block_hash=previous_block.hash,
150
152
  timestamp=previous_block.timestamp + 1,
151
153
  accounts_hash=previous_block.accounts_hash,
152
154
  transaction_limit=previous_block.transaction_limit,
153
155
  transactions_count=0,
156
+ validator_pk=validator_sk.public_key().public_bytes(),
154
157
  )
155
158
 
156
- # --- 1. apply up to transaction_limit txs -------------------------------
159
+ # ------------------ difficulty via natural_rate -----------------------
160
+ prev_bt = previous_block.block_time or 0
161
+ prev_diff = previous_block.delay_difficulty or 1
162
+ if prev_bt <= 1:
163
+ blk.delay_difficulty = max(1, int(prev_diff / natural_rate)) # increase
164
+ else:
165
+ blk.delay_difficulty = max(1, int(prev_diff * natural_rate)) # decrease
166
+
167
+ # ------------------ launch VDF in background --------------------------
168
+ vdf_result: dict[str, bytes] = {}
169
+
170
+ def _vdf_worker():
171
+ y, p = vdf_generate(previous_block.delay_output, blk.delay_difficulty, -4)
172
+ vdf_result["y"] = y
173
+ vdf_result["p"] = p
174
+
175
+ Thread(target=_vdf_worker, daemon=True).start()
176
+
177
+ # ------------------ process transactions -----------------------------
157
178
  for tx in transactions:
158
179
  try:
159
- blk.apply_tx(tx) # ← NEW single-line call
180
+ blk.apply_tx(tx)
160
181
  except ValueError:
161
- break # stop at first invalid or cap reached
182
+ break
162
183
 
163
- # --- 2. split fees after all txs ----------------------------------------
184
+ # ------------------ split fees --------------------------------------
164
185
  burn_amt = blk.total_fees // 2
165
186
  reward_amt = blk.total_fees - burn_amt
187
+
188
+ def _credit(addr: bytes, amt: int):
189
+ acc = blk.accounts.get_account(addr) or Account.create(0, b"", 0)
190
+ blk.accounts.set_account(addr, Account.create(acc.balance() + amt, acc.data(), acc.nonce()))
191
+
166
192
  if burn_amt:
167
- blk.accounts.set_account(
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
- )
193
+ _credit(BURN, burn_amt)
175
194
  if reward_amt:
176
- blk.accounts.set_account(
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
- )
195
+ _credit(blk.validator_pk, reward_amt)
184
196
 
185
- # --- 3. recalc tx-limit via prev metrics -------------------------------
197
+ # ------------------ update tx limit with natural_rate ---------------
186
198
  prev_limit = previous_block.transaction_limit
187
199
  prev_tx_count = previous_block.transactions_count
188
- threshold = prev_limit * natural_rate
189
- if prev_tx_count > threshold:
200
+ grow_thr = prev_limit * natural_rate
201
+ shrink_thr = prev_tx_count * natural_rate
202
+
203
+ if prev_tx_count > grow_thr:
190
204
  blk.transaction_limit = prev_tx_count
191
- elif prev_tx_count < threshold:
205
+ elif prev_tx_count < shrink_thr:
192
206
  blk.transaction_limit = max(1, int(prev_limit * natural_rate))
193
207
  else:
194
208
  blk.transaction_limit = prev_limit
195
209
 
196
- # --- 4. finalise block hash & header roots ------------------------------
210
+ # ------------------ wait for VDF ------------------------------------
211
+ while "y" not in vdf_result:
212
+ pass
213
+ blk.delay_output = vdf_result["y"]
214
+ blk.delay_proof = vdf_result["p"]
215
+
216
+ # ------------------ timing & roots ----------------------------------
217
+ blk.block_time = blk.timestamp - previous_block.timestamp
197
218
  blk.accounts_hash = blk.accounts.root_hash
198
219
  blk.transactions_root_hash = MerkleTree.from_leaves(blk.tx_hashes).root_hash
199
- blk.hash = MerkleTree.from_leaves([
200
- blk.transactions_root_hash,
201
- blk.accounts_hash,
202
- blk.total_fees.to_bytes(8, "big"),
203
- ]).root_hash # or your existing body-root/signing scheme
220
+ blk.transactions_total_fees = blk.total_fees
221
+
222
+ # ------------------ build full body root ----------------------------
223
+ body_fields = {
224
+ "accounts_hash": blk.accounts_hash,
225
+ "block_time": blk.block_time,
226
+ "delay_difficulty": blk.delay_difficulty,
227
+ "delay_output": blk.delay_output,
228
+ "delay_proof": blk.delay_proof,
229
+ "number": blk.number,
230
+ "prev_block_hash": blk.prev_block_hash,
231
+ "timestamp": blk.timestamp,
232
+ "transaction_limit": blk.transaction_limit,
233
+ "transactions_count": blk.transactions_count,
234
+ "transactions_root_hash": blk.transactions_root_hash,
235
+ "transactions_total_fees": blk.transactions_total_fees,
236
+ "validator_pk": blk.validator_pk,
237
+ }
238
+
239
+ leaves: List[bytes] = []
240
+ for k in sorted(body_fields):
241
+ v = body_fields[k]
242
+ if isinstance(v, bytes):
243
+ leaves.append(v)
244
+ else:
245
+ leaves.append(int(v).to_bytes((v.bit_length() + 7) // 8 or 1, "big"))
246
+
247
+ body_root = MerkleTree.from_leaves(leaves).root_hash
248
+ blk.body_tree = MerkleTree.from_leaves([body_root])
249
+ blk.signature = validator_sk.sign(body_root)
250
+ blk.hash = MerkleTree.from_leaves([body_root, blk.signature]).root_hash
204
251
 
205
252
  return blk
206
253
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astreum
3
- Version: 0.2.24
3
+ Version: 0.2.25
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=FDAX82L5cceR6DGTtUO57ZhcxpBNiskGrnLWnd_3BSw,4084
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=mqHpsN4-aDyW9Q9emFBVIEyNvLAqRJZbqCN-4vS4Hw0,11795
15
+ astreum/models/block.py,sha256=4slG6z6pZUyxQUu2on4c8nT24ztzJuQBZRje9KyRTXE,13840
16
16
  astreum/models/merkle.py,sha256=merV3rx2iRfzvglV6gNusrJf7OMbcVV854T-DUWCC64,6733
17
17
  astreum/models/patricia.py,sha256=ohmXrcaz7Ae561tyC4u4iPOkQPkKr8N0IWJek4upFIg,13392
18
18
  astreum/models/transaction.py,sha256=yBarvRK2ybMAHHEQPZpubGO7gms4U9k093xQGNQHQ4Q,3043
19
- astreum-0.2.24.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
20
- astreum-0.2.24.dist-info/METADATA,sha256=bcrWSsFCFwM884WECJ9THr12tMUS8MAG3VwLyaCEosg,5478
21
- astreum-0.2.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- astreum-0.2.24.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
23
- astreum-0.2.24.dist-info/RECORD,,
19
+ astreum-0.2.25.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
20
+ astreum-0.2.25.dist-info/METADATA,sha256=BqaRK8hea6p3iMUkin5gqzivjdOz16_alamM9jFkteQ,5478
21
+ astreum-0.2.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
+ astreum-0.2.25.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
23
+ astreum-0.2.25.dist-info/RECORD,,