astreum 0.3.1__py3-none-any.whl → 0.3.16__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.
Files changed (38) hide show
  1. astreum/__init__.py +4 -2
  2. astreum/communication/handlers/handshake.py +62 -83
  3. astreum/communication/handlers/object_request.py +176 -0
  4. astreum/communication/handlers/object_response.py +115 -0
  5. astreum/communication/handlers/ping.py +6 -20
  6. astreum/communication/handlers/route_request.py +76 -0
  7. astreum/communication/handlers/route_response.py +53 -0
  8. astreum/communication/models/message.py +81 -58
  9. astreum/communication/models/peer.py +42 -14
  10. astreum/communication/models/route.py +2 -7
  11. astreum/communication/processors/__init__.py +0 -0
  12. astreum/communication/processors/incoming.py +98 -0
  13. astreum/communication/processors/outgoing.py +20 -0
  14. astreum/communication/processors/peer.py +59 -0
  15. astreum/communication/setup.py +39 -76
  16. astreum/communication/start.py +9 -10
  17. astreum/communication/util.py +7 -0
  18. astreum/consensus/start.py +9 -10
  19. astreum/consensus/validator.py +17 -8
  20. astreum/consensus/workers/discovery.py +6 -7
  21. astreum/consensus/workers/validation.py +334 -291
  22. astreum/consensus/workers/verify.py +8 -10
  23. astreum/crypto/chacha20poly1305.py +74 -0
  24. astreum/machine/evaluations/high_evaluation.py +237 -237
  25. astreum/machine/evaluations/low_evaluation.py +18 -18
  26. astreum/node.py +29 -7
  27. astreum/storage/actions/get.py +183 -69
  28. astreum/storage/actions/set.py +66 -20
  29. astreum/storage/requests.py +28 -0
  30. astreum/storage/setup.py +3 -25
  31. astreum/utils/config.py +76 -0
  32. {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/METADATA +3 -3
  33. astreum-0.3.16.dist-info/RECORD +72 -0
  34. astreum/communication/handlers/storage_request.py +0 -81
  35. astreum-0.3.1.dist-info/RECORD +0 -62
  36. {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/WHEEL +0 -0
  37. {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/licenses/LICENSE +0 -0
  38. {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/top_level.txt +0 -0
@@ -40,3 +40,10 @@ def address_str_to_host_and_port(address: str) -> Tuple[str, int]:
40
40
  raise ValueError(f"port out of range: {port}")
41
41
 
42
42
  return host, port
43
+
44
+
45
+ def xor_distance(a: bytes, b: bytes) -> int:
46
+ """Return the unsigned integer XOR distance between two equal-length identifiers."""
47
+ if len(a) != len(b):
48
+ raise ValueError("xor distance requires operands of equal length")
49
+ return int.from_bytes(bytes(x ^ y for x, y in zip(a, b)), "big", signed=False)
@@ -6,10 +6,9 @@ from astreum.consensus.genesis import create_genesis_block
6
6
 
7
7
  def process_blocks_and_transactions(self, validator_secret_key: Ed25519PrivateKey):
8
8
  """Initialize validator keys, ensure genesis exists, then start validation thread."""
9
- node_logger = self.logger
10
- node_logger.info(
9
+ self.logger.info(
11
10
  "Initializing block and transaction processing for chain %s",
12
- getattr(self, "chain", "unknown"),
11
+ self.config["chain"],
13
12
  )
14
13
 
15
14
  self.validation_secret_key = validator_secret_key
@@ -19,7 +18,7 @@ def process_blocks_and_transactions(self, validator_secret_key: Ed25519PrivateKe
19
18
  format=serialization.PublicFormat.Raw,
20
19
  )
21
20
  self.validation_public_key = validator_public_key_bytes
22
- node_logger.debug(
21
+ self.logger.debug(
23
22
  "Derived validator public key %s", validator_public_key_bytes.hex()
24
23
  )
25
24
 
@@ -27,12 +26,12 @@ def process_blocks_and_transactions(self, validator_secret_key: Ed25519PrivateKe
27
26
  genesis_block = create_genesis_block(
28
27
  self,
29
28
  validator_public_key=validator_public_key_bytes,
30
- chain_id=self.chain,
29
+ chain_id=self.config["chain_id"],
31
30
  )
32
31
  account_atoms = genesis_block.accounts.update_trie(self) if genesis_block.accounts else []
33
32
 
34
33
  genesis_hash, genesis_atoms = genesis_block.to_atom()
35
- node_logger.debug(
34
+ self.logger.debug(
36
35
  "Genesis block created with %s atoms (%s account atoms)",
37
36
  len(genesis_atoms),
38
37
  len(account_atoms),
@@ -42,7 +41,7 @@ def process_blocks_and_transactions(self, validator_secret_key: Ed25519PrivateKe
42
41
  try:
43
42
  self._hot_storage_set(key=atom.object_id(), value=atom)
44
43
  except Exception as exc:
45
- node_logger.warning(
44
+ self.logger.warning(
46
45
  "Unable to persist genesis atom %s: %s",
47
46
  atom.object_id(),
48
47
  exc,
@@ -50,16 +49,16 @@ def process_blocks_and_transactions(self, validator_secret_key: Ed25519PrivateKe
50
49
 
51
50
  self.latest_block_hash = genesis_hash
52
51
  self.latest_block = genesis_block
53
- node_logger.info("Genesis block stored with hash %s", genesis_hash.hex())
52
+ self.logger.info("Genesis block stored with hash %s", genesis_hash.hex())
54
53
  else:
55
- node_logger.debug(
54
+ self.logger.debug(
56
55
  "latest_block_hash already set to %s; skipping genesis creation",
57
56
  self.latest_block_hash.hex()
58
57
  if isinstance(self.latest_block_hash, (bytes, bytearray))
59
58
  else self.latest_block_hash,
60
59
  )
61
60
 
62
- node_logger.info(
61
+ self.logger.info(
63
62
  "Starting consensus validation thread (%s)",
64
63
  self.consensus_validation_thread.name,
65
64
  )
@@ -11,15 +11,19 @@ from ..storage.models.atom import ZERO32
11
11
  from ..utils.integer import bytes_to_int, int_to_bytes
12
12
 
13
13
 
14
+ SLOT_DURATION_SECONDS = 2
15
+
16
+
14
17
  def current_validator(
15
18
  node: Any,
16
19
  block_hash: bytes,
17
20
  target_time: Optional[int] = None,
18
21
  ) -> Tuple[bytes, Accounts]:
19
22
  """
20
- Determine the validator for the requested target_time, halving stakes each second
21
- between the referenced block and the target time. Returns the validator key and
22
- the updated accounts snapshot reflecting stake and balance adjustments.
23
+ Determine the validator for the requested target_time, halving stakes once per
24
+ slot (currently 2 seconds) between the referenced block and the target time.
25
+ Returns the validator key and the updated accounts snapshot reflecting stake and
26
+ balance adjustments.
23
27
  """
24
28
 
25
29
  block = Block.from_atom(node, block_hash)
@@ -74,6 +78,8 @@ def current_validator(
74
78
  if current_amount <= 0:
75
79
  raise ValueError("validator stake must be positive")
76
80
  new_amount = current_amount // 2
81
+ if new_amount < 1:
82
+ new_amount = 1
77
83
  returned_amount = current_amount - new_amount
78
84
  stakes[validator_key] = new_amount
79
85
  stake_trie.put(node, validator_key, int_to_bytes(new_amount))
@@ -86,10 +92,13 @@ def current_validator(
86
92
  accounts.set_account(validator_key, validator_account)
87
93
  accounts.set_account(TREASURY_ADDRESS, treasury_account)
88
94
 
89
- iteration_target = block_timestamp + 1
90
- while True:
95
+ delta = target_timestamp - block_timestamp
96
+ slots_to_process = max(1, (delta + SLOT_DURATION_SECONDS - 1) // SLOT_DURATION_SECONDS)
97
+
98
+ selected_validator = pick_validator()
99
+ halve_stake(selected_validator)
100
+ for _ in range(1, slots_to_process):
91
101
  selected_validator = pick_validator()
92
102
  halve_stake(selected_validator)
93
- if iteration_target == target_timestamp:
94
- return selected_validator, accounts
95
- iteration_target += 1
103
+
104
+ return selected_validator, accounts
@@ -13,8 +13,7 @@ def make_discovery_worker(node: Any):
13
13
  """
14
14
 
15
15
  def _discovery_worker() -> None:
16
- node_logger = node.logger
17
- node_logger.info("Discovery worker started")
16
+ node.logger.info("Discovery worker started")
18
17
  stop = node._validation_stop_event
19
18
  while not stop.is_set():
20
19
  try:
@@ -36,10 +35,10 @@ def make_discovery_worker(node: Any):
36
35
  }
37
36
 
38
37
  if not pairs:
39
- node_logger.debug("No peers reported latest blocks; skipping queue update")
38
+ node.logger.debug("No peers reported latest blocks; skipping queue update")
40
39
  continue
41
40
 
42
- node_logger.debug(
41
+ node.logger.debug(
43
42
  "Discovery grouped %d block hashes from %d peers",
44
43
  len(grouped),
45
44
  len(pairs),
@@ -52,16 +51,16 @@ def make_discovery_worker(node: Any):
52
51
  pass
53
52
  for latest_b, peer_set in grouped.items():
54
53
  node._validation_verify_queue.put((latest_b, peer_set))
55
- node_logger.debug(
54
+ node.logger.debug(
56
55
  "Queued %d peers for validation of block %s",
57
56
  len(peer_set),
58
57
  latest_b.hex(),
59
58
  )
60
59
  except Exception:
61
- node_logger.exception("Discovery worker iteration failed")
60
+ node.logger.exception("Discovery worker iteration failed")
62
61
  finally:
63
62
  time.sleep(0.5)
64
63
 
65
- node_logger.info("Discovery worker stopped")
64
+ node.logger.info("Discovery worker stopped")
66
65
 
67
66
  return _discovery_worker