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.
- astreum/__init__.py +4 -2
- astreum/communication/handlers/handshake.py +62 -83
- astreum/communication/handlers/object_request.py +176 -0
- astreum/communication/handlers/object_response.py +115 -0
- astreum/communication/handlers/ping.py +6 -20
- astreum/communication/handlers/route_request.py +76 -0
- astreum/communication/handlers/route_response.py +53 -0
- astreum/communication/models/message.py +81 -58
- astreum/communication/models/peer.py +42 -14
- astreum/communication/models/route.py +2 -7
- astreum/communication/processors/__init__.py +0 -0
- astreum/communication/processors/incoming.py +98 -0
- astreum/communication/processors/outgoing.py +20 -0
- astreum/communication/processors/peer.py +59 -0
- astreum/communication/setup.py +39 -76
- astreum/communication/start.py +9 -10
- astreum/communication/util.py +7 -0
- astreum/consensus/start.py +9 -10
- astreum/consensus/validator.py +17 -8
- astreum/consensus/workers/discovery.py +6 -7
- astreum/consensus/workers/validation.py +334 -291
- astreum/consensus/workers/verify.py +8 -10
- astreum/crypto/chacha20poly1305.py +74 -0
- astreum/machine/evaluations/high_evaluation.py +237 -237
- astreum/machine/evaluations/low_evaluation.py +18 -18
- astreum/node.py +29 -7
- astreum/storage/actions/get.py +183 -69
- astreum/storage/actions/set.py +66 -20
- astreum/storage/requests.py +28 -0
- astreum/storage/setup.py +3 -25
- astreum/utils/config.py +76 -0
- {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/METADATA +3 -3
- astreum-0.3.16.dist-info/RECORD +72 -0
- astreum/communication/handlers/storage_request.py +0 -81
- astreum-0.3.1.dist-info/RECORD +0 -62
- {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/WHEEL +0 -0
- {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.3.1.dist-info → astreum-0.3.16.dist-info}/top_level.txt +0 -0
astreum/communication/util.py
CHANGED
|
@@ -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)
|
astreum/consensus/start.py
CHANGED
|
@@ -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
|
-
|
|
10
|
-
node_logger.info(
|
|
9
|
+
self.logger.info(
|
|
11
10
|
"Initializing block and transaction processing for chain %s",
|
|
12
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
52
|
+
self.logger.info("Genesis block stored with hash %s", genesis_hash.hex())
|
|
54
53
|
else:
|
|
55
|
-
|
|
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
|
-
|
|
61
|
+
self.logger.info(
|
|
63
62
|
"Starting consensus validation thread (%s)",
|
|
64
63
|
self.consensus_validation_thread.name,
|
|
65
64
|
)
|
astreum/consensus/validator.py
CHANGED
|
@@ -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
|
|
21
|
-
between the referenced block and the target time.
|
|
22
|
-
the updated accounts snapshot reflecting stake and
|
|
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
|
-
|
|
90
|
-
|
|
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
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
38
|
+
node.logger.debug("No peers reported latest blocks; skipping queue update")
|
|
40
39
|
continue
|
|
41
40
|
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
60
|
+
node.logger.exception("Discovery worker iteration failed")
|
|
62
61
|
finally:
|
|
63
62
|
time.sleep(0.5)
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
node.logger.info("Discovery worker stopped")
|
|
66
65
|
|
|
67
66
|
return _discovery_worker
|