astreum 0.2.61__py3-none-any.whl → 0.3.9__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 (86) hide show
  1. astreum/__init__.py +16 -7
  2. astreum/{_communication → communication}/__init__.py +3 -3
  3. astreum/communication/handlers/handshake.py +89 -0
  4. astreum/communication/handlers/object_request.py +176 -0
  5. astreum/communication/handlers/object_response.py +115 -0
  6. astreum/communication/handlers/ping.py +34 -0
  7. astreum/communication/handlers/route_request.py +76 -0
  8. astreum/communication/handlers/route_response.py +53 -0
  9. astreum/communication/models/__init__.py +0 -0
  10. astreum/communication/models/message.py +124 -0
  11. astreum/communication/models/peer.py +51 -0
  12. astreum/{_communication → communication/models}/route.py +7 -12
  13. astreum/communication/processors/__init__.py +0 -0
  14. astreum/communication/processors/incoming.py +98 -0
  15. astreum/communication/processors/outgoing.py +20 -0
  16. astreum/communication/setup.py +166 -0
  17. astreum/communication/start.py +37 -0
  18. astreum/{_communication → communication}/util.py +7 -0
  19. astreum/consensus/__init__.py +20 -0
  20. astreum/consensus/genesis.py +66 -0
  21. astreum/consensus/models/__init__.py +0 -0
  22. astreum/consensus/models/account.py +84 -0
  23. astreum/consensus/models/accounts.py +72 -0
  24. astreum/consensus/models/block.py +364 -0
  25. astreum/{_consensus → consensus/models}/chain.py +7 -7
  26. astreum/{_consensus → consensus/models}/fork.py +8 -8
  27. astreum/consensus/models/receipt.py +98 -0
  28. astreum/{_consensus → consensus/models}/transaction.py +76 -78
  29. astreum/{_consensus → consensus}/setup.py +18 -50
  30. astreum/consensus/start.py +67 -0
  31. astreum/consensus/validator.py +95 -0
  32. astreum/{_consensus → consensus}/workers/discovery.py +19 -1
  33. astreum/consensus/workers/validation.py +307 -0
  34. astreum/{_consensus → consensus}/workers/verify.py +29 -2
  35. astreum/crypto/chacha20poly1305.py +74 -0
  36. astreum/machine/__init__.py +20 -0
  37. astreum/machine/evaluations/__init__.py +0 -0
  38. astreum/{_lispeum → machine/evaluations}/high_evaluation.py +237 -236
  39. astreum/machine/evaluations/low_evaluation.py +281 -0
  40. astreum/machine/evaluations/script_evaluation.py +27 -0
  41. astreum/machine/models/__init__.py +0 -0
  42. astreum/machine/models/environment.py +31 -0
  43. astreum/{_lispeum → machine/models}/expression.py +36 -8
  44. astreum/machine/tokenizer.py +90 -0
  45. astreum/node.py +78 -767
  46. astreum/storage/__init__.py +7 -0
  47. astreum/storage/actions/get.py +183 -0
  48. astreum/storage/actions/set.py +178 -0
  49. astreum/{_storage → storage/models}/atom.py +55 -57
  50. astreum/{_storage/patricia.py → storage/models/trie.py} +227 -203
  51. astreum/storage/requests.py +28 -0
  52. astreum/storage/setup.py +22 -15
  53. astreum/utils/config.py +48 -0
  54. {astreum-0.2.61.dist-info → astreum-0.3.9.dist-info}/METADATA +27 -26
  55. astreum-0.3.9.dist-info/RECORD +71 -0
  56. astreum/_communication/message.py +0 -101
  57. astreum/_communication/peer.py +0 -23
  58. astreum/_communication/setup.py +0 -322
  59. astreum/_consensus/__init__.py +0 -20
  60. astreum/_consensus/account.py +0 -95
  61. astreum/_consensus/accounts.py +0 -38
  62. astreum/_consensus/block.py +0 -311
  63. astreum/_consensus/genesis.py +0 -72
  64. astreum/_consensus/receipt.py +0 -136
  65. astreum/_consensus/workers/validation.py +0 -125
  66. astreum/_lispeum/__init__.py +0 -16
  67. astreum/_lispeum/environment.py +0 -13
  68. astreum/_lispeum/low_evaluation.py +0 -123
  69. astreum/_lispeum/tokenizer.py +0 -22
  70. astreum/_node.py +0 -198
  71. astreum/_storage/__init__.py +0 -7
  72. astreum/_storage/setup.py +0 -35
  73. astreum/format.py +0 -75
  74. astreum/models/block.py +0 -441
  75. astreum/models/merkle.py +0 -205
  76. astreum/models/patricia.py +0 -393
  77. astreum/storage/object.py +0 -68
  78. astreum-0.2.61.dist-info/RECORD +0 -57
  79. /astreum/{models → communication/handlers}/__init__.py +0 -0
  80. /astreum/{_communication → communication/models}/ping.py +0 -0
  81. /astreum/{_consensus → consensus}/workers/__init__.py +0 -0
  82. /astreum/{_lispeum → machine/models}/meter.py +0 -0
  83. /astreum/{_lispeum → machine}/parser.py +0 -0
  84. {astreum-0.2.61.dist-info → astreum-0.3.9.dist-info}/WHEEL +0 -0
  85. {astreum-0.2.61.dist-info → astreum-0.3.9.dist-info}/licenses/LICENSE +0 -0
  86. {astreum-0.2.61.dist-info → astreum-0.3.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,48 @@
1
+
2
+ from pathlib import Path
3
+ from typing import Dict
4
+
5
+ DEFAULT_HOT_STORAGE_LIMIT = 1 << 30 # 1 GiB
6
+ DEFAULT_COLD_STORAGE_LIMIT = 10 << 30 # 10 GiB
7
+
8
+
9
+ def config_setup(config: Dict = {}):
10
+ """
11
+ Normalize configuration values before the node starts.
12
+ """
13
+ chain_str = config.get("chain", "test")
14
+ if chain_str not in {"main", "test"}:
15
+ chain_str = "test"
16
+ config["chain"] = chain_str
17
+ config["chain_id"] = 1 if chain_str == "main" else 0
18
+
19
+ hot_limit_raw = config.get(
20
+ "hot_storage_limit", config.get("hot_storage_default_limit", DEFAULT_HOT_STORAGE_LIMIT)
21
+ )
22
+ try:
23
+ config["hot_storage_default_limit"] = int(hot_limit_raw)
24
+ except (TypeError, ValueError) as exc:
25
+ raise ValueError(
26
+ f"hot_storage_limit must be an integer: {hot_limit_raw!r}"
27
+ ) from exc
28
+
29
+ cold_limit_raw = config.get("cold_storage_limit", DEFAULT_COLD_STORAGE_LIMIT)
30
+ try:
31
+ config["cold_storage_limit"] = int(cold_limit_raw)
32
+ except (TypeError, ValueError) as exc:
33
+ raise ValueError(
34
+ f"cold_storage_limit must be an integer: {cold_limit_raw!r}"
35
+ ) from exc
36
+
37
+ cold_path_raw = config.get("cold_storage_path")
38
+ if cold_path_raw:
39
+ try:
40
+ path_obj = Path(cold_path_raw)
41
+ path_obj.mkdir(parents=True, exist_ok=True)
42
+ config["cold_storage_path"] = str(path_obj)
43
+ except OSError:
44
+ config["cold_storage_path"] = None
45
+ else:
46
+ config["cold_storage_path"] = None
47
+
48
+ return config
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astreum
3
- Version: 0.2.61
4
- Summary: Python library to interact with the Astreum blockchain and its Lispeum virtual machine.
3
+ Version: 0.3.9
4
+ Summary: Python library to interact with the Astreum blockchain and its virtual machine.
5
5
  Author-email: "Roy R. O. Okello" <roy@stelar.xyz>
6
- Project-URL: Homepage, https://github.com/astreum/lib
7
- Project-URL: Issues, https://github.com/astreum/lib/issues
6
+ Project-URL: Homepage, https://github.com/astreum/lib-py
7
+ Project-URL: Issues, https://github.com/astreum/lib-py/issues
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
@@ -18,7 +18,7 @@ Dynamic: license-file
18
18
 
19
19
  # lib
20
20
 
21
- Python library to interact with the Astreum blockchain and its Lispeum virtual machine.
21
+ Python library to interact with the Astreum blockchain and its virtual machine.
22
22
 
23
23
  [View on PyPI](https://pypi.org/project/astreum/)
24
24
 
@@ -30,21 +30,21 @@ When initializing an `astreum.Node`, pass a dictionary with any of the options b
30
30
 
31
31
  | Parameter | Type | Default | Description |
32
32
  | --------------------------- | ---------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
33
- | `machine-only` | bool | `True` | When **True** the node starts in *machine‑only* mode: no storage subsystem and no relay networking – only the Lispeum VM. Set to **False** to enable storage and relay features. |
34
- | `relay_secret_key` | hex string | Auto‑generated | Ed25519 private key that identifies the node on the network. If omitted, a fresh keypair is generated and kept in‑memory. |
35
- | `validation_secret_key` | hex string | `None` | X25519 private key that lets the node participate in the validation route. Leave unset for a non‑validator node. |
36
- | `storage_path` | string | `None` | Directory where objects are persisted. If *None*, the node uses an in‑memory store. |
37
- | `storage_get_relay_timeout` | float | `5` | Seconds to wait for an object requested from peers before timing‑out. |
33
+ | `hot_storage_limit` | int | `1073741824` | Maximum bytes kept in the hot cache before new atoms are skipped (1 GiB). |
34
+ | `cold_storage_limit` | int | `10737418240` | Cold storage write threshold (10 GiB by default); set to `0` to skip the limit. |
35
+ | `cold_storage_path` | string | `None` | Directory where persisted atoms live; Astreum creates it on startup and skips cold storage when unset. |
38
36
  | `logging_retention` | int | `90` | Number of days to keep rotated log files (daily gzip). |
39
37
  | `verbose` | bool | `False` | When **True**, also mirror JSON logs to stdout with a human-readable format. |
40
38
 
41
39
  ### Networking
42
40
 
43
- | Parameter | Type | Default | Description |
44
- | --------------- | ----------------------- | ------- | ----------------------------------------------------------------------------------- |
45
- | `use_ipv6` | bool | `False` | Listen on IPv6 as well as IPv4. |
46
- | `incoming_port` | int | `7373` | UDP port the relay binds to. |
47
- | `bootstrap` | list\[tuple\[str, int]] | `[]` | Initial peers used to join the network, e.g. `[ ("bootstrap.astreum.org", 7373) ]`. |
41
+ | Parameter | Type | Default | Description |
42
+ | ------------------------ | ----------- | --------------------- | ------------------------------------------------------------------------------------------------------- |
43
+ | `relay_secret_key` | hex string | Auto-generated | X25519 private key used for the relay route; a new keypair is created when this field is omitted. |
44
+ | `validation_secret_key` | hex string | `None` | Optional Ed25519 key that lets the node join the validation route; leave blank to opt out of validation. |
45
+ | `use_ipv6` | bool | `False` | Bind the incoming/outgoing sockets on IPv6 (the OS still listens on IPv4 if a peer speaks both). |
46
+ | `incoming_port` | int | `7373` | UDP port the relay binds to; pass `0` or omit to let the OS pick an ephemeral port. |
47
+ | `bootstrap` | list\[str\] | `[]` | Addresses to ping with a handshake before joining; each must look like `host:port` or `[ipv6]:port`. |
48
48
 
49
49
  > **Note**
50
50
  > The peer‑to‑peer *route* used for object discovery is always enabled.
@@ -56,16 +56,16 @@ When initializing an `astreum.Node`, pass a dictionary with any of the options b
56
56
  from astreum.node import Node
57
57
 
58
58
  config = {
59
- "machine-only": False, # run full node
60
59
  "relay_secret_key": "ab…cd", # optional – hex encoded
61
60
  "validation_secret_key": "12…34", # optional – validator
62
- "storage_path": "./data/node1",
63
- "storage_get_relay_timeout": 5,
61
+ "hot_storage_limit": 1073741824, # cap hot cache at 1 GiB
62
+ "cold_storage_limit": 10737418240, # cap cold storage at 10 GiB
63
+ "cold_storage_path": "./data/node1",
64
64
  "incoming_port": 7373,
65
65
  "use_ipv6": False,
66
66
  "bootstrap": [
67
- ("bootstrap.astreum.org", 7373),
68
- ("127.0.0.1", 7374)
67
+ "bootstrap.astreum.org:7373",
68
+ "127.0.0.1:7374"
69
69
  ]
70
70
  }
71
71
 
@@ -73,9 +73,10 @@ node = Node(config)
73
73
  # … your code …
74
74
  ```
75
75
 
76
- ## Lispeum Machine Quickstart
77
76
 
78
- The Lispeum virtual machine (VM) is embedded inside `astreum.Node`. You feed it Lispeum source text, and the node tokenizes, parses, and **evaluates** the resulting AST inside an isolated environment.
77
+ ## Astreum Machine Quickstart
78
+
79
+ The Astreum virtual machine (VM) is embedded inside `astreum.Node`. You feed it Astreum script, and the node tokenizes, parses, and evaluates.
79
80
 
80
81
  ```python
81
82
  # Define a named function int.add (stack body) and call it with bytes 1 and 2
@@ -108,15 +109,15 @@ params = Expr.ListExpr([Expr.Symbol("a"), Expr.Symbol("b")])
108
109
  int_add_fn = Expr.ListExpr([fn_body, params, Expr.Symbol("fn")])
109
110
 
110
111
  # 4) Store under the name "int.add"
111
- node.env_set(env_id, b"int.add", int_add_fn)
112
+ node.env_set(env_id, "int.add", int_add_fn)
112
113
 
113
114
  # 5) Retrieve the function and call it with bytes 1 and 2
114
- bound = node.env_get(env_id, b"int.add")
115
- call = Expr.ListExpr([Expr.Byte(1), Expr.Byte(2), bound])
115
+ bound = node.env_get(env_id, "int.add")
116
+ call = Expr.ListExpr([Expr.Bytes(b"\x01"), Expr.Bytes(b"\x02"), bound])
116
117
  res = node.high_eval(env_id, call)
117
118
 
118
119
  # sk returns a list of bytes; for 1+2 expect a single byte with value 3
119
- print([b.value for b in res.elements]) # [3]
120
+ print([int.from_bytes(b.value, 'big', signed=True) for b in res.elements]) # [3]
120
121
  ```
121
122
 
122
123
  ### Handling errors
@@ -0,0 +1,71 @@
1
+ astreum/__init__.py,sha256=GkEW_ReYore8_0nEOvPnZLUa3lO7CgMWu6LeEjrGXEk,325
2
+ astreum/node.py,sha256=naKGkn97M3Khux3r8mZ81wsiAI6JFr4uhly4X_BspmU,2689
3
+ astreum/communication/__init__.py,sha256=wNxzsAk8Fol9cGMPuVvY4etrrMqn3SjZq1dE82kFrxw,228
4
+ astreum/communication/setup.py,sha256=We43HOZG0v18TZhEdkc8MWCvI9YvHw8s4fmauHEXDUc,5887
5
+ astreum/communication/start.py,sha256=wxL1cgChebhnaeEaY9flS6qybo_cFW2-tcRvjLxC8Hw,1823
6
+ astreum/communication/util.py,sha256=fS3u3giOOXmvN0_reb0oIaXsFESHAWz-bbAuzdzdGQ4,1575
7
+ astreum/communication/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ astreum/communication/handlers/handshake.py,sha256=79Y5ei8RHg53WIwzP1eO4dpDYdKvhr1qrbWMECf9D-E,2781
9
+ astreum/communication/handlers/object_request.py,sha256=n_ThJomdYXm6HPfkLMmCqRxO58xPCUOHXf1ddmG-OC8,7163
10
+ astreum/communication/handlers/object_response.py,sha256=X5MfYxd_b4SfKq3129Fi29ZfLynWNRyhGuoISiMHy20,3959
11
+ astreum/communication/handlers/ping.py,sha256=2fVynfVIsbWHtf7lpM6fTYWmeG0I1WSU3tmgCh9di7A,916
12
+ astreum/communication/handlers/route_request.py,sha256=KrucRgiM_oFNmwt93bRzNpeVHFATq3uhlNjGJIvzu-c,2477
13
+ astreum/communication/handlers/route_response.py,sha256=ZUKyXPpZzpVYKBgygMIlPjcmjrxi0s8M3COFfY5aO4A,1744
14
+ astreum/communication/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ astreum/communication/models/message.py,sha256=2qln_PpKkVEoPdSGeQxUWAFxcEsHB-lz7dzTAsO94HU,4485
16
+ astreum/communication/models/peer.py,sha256=834UyyErBGbZs4dxe_SWz3gnRGnvFyc-7XQPrdNvDFE,1669
17
+ astreum/communication/models/ping.py,sha256=u_DQTZJsbMdYiDDqjdZDsLaN5na2m9WZjVeEM3zq9_Y,955
18
+ astreum/communication/models/route.py,sha256=NdmnI1J1wFs2pkm6W0Kv-29JeqGiHcKlw4-esT5ZFLA,3797
19
+ astreum/communication/processors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ astreum/communication/processors/incoming.py,sha256=10l6Az-Ul_2BvYpTXgPiL9bL0te1q3GB3aET0JednKE,3325
21
+ astreum/communication/processors/outgoing.py,sha256=09nAeTzvo3jGWl3SLgIQr8vfmO_IvdDqSG7_ZKThYPk,593
22
+ astreum/consensus/__init__.py,sha256=VZR_NyGSD5VvZp3toD2zpdYwFDLBIcckeVZXFPlruuU,425
23
+ astreum/consensus/genesis.py,sha256=RI9AzQFmDTgNFuiiTmW2dDiGcURIUGmThdRpxWrUOBk,1962
24
+ astreum/consensus/setup.py,sha256=lrEapfpJXKqw4iwST11-tqPAI2VW2h3H6Ue4JDAtrP4,3142
25
+ astreum/consensus/start.py,sha256=DM45Pw6JL5rew-KpcspINguH43ZUHr4v99tXjYqaEkE,2551
26
+ astreum/consensus/validator.py,sha256=cqcmw1WEB8DkznNX_Mn8tmE956rVSNCPv1FicdL8EAQ,3647
27
+ astreum/consensus/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ astreum/consensus/models/account.py,sha256=3QcT59QUZynysLSbiywidFYVzYJ3LR6qia7JwXOwn4I,2690
29
+ astreum/consensus/models/accounts.py,sha256=iUMs6LvmMea-gxd6-ujkFjqhWmuW1cl9XTWGXQkpLys,2388
30
+ astreum/consensus/models/block.py,sha256=nNtw9TbEAF1mIEfgJr1fuswcZ0B63SVnuBANqJ5Zaac,13531
31
+ astreum/consensus/models/chain.py,sha256=SIIDFSYbag76kTUNwnuJ2_zyuhFsvT7n5HgrVTxBrvE,2797
32
+ astreum/consensus/models/fork.py,sha256=IbXRB93bUg2k3q3oQ9dOPzozV-rY-TEDFjYrw-WBymE,3859
33
+ astreum/consensus/models/receipt.py,sha256=KjKKjYp_LnP2zkX1FLIwD_4hqKV1b2TPfp43tY701q4,3336
34
+ astreum/consensus/models/transaction.py,sha256=AYa1Q-BaYW3mkOv1e3WbvDFEsYamKMiFrja-eO2zU_Y,7475
35
+ astreum/consensus/workers/__init__.py,sha256=bS5FjbevbIR5FHbVGnT4Jli17VIld_5auemRw4CaHFU,278
36
+ astreum/consensus/workers/discovery.py,sha256=u6HyxamMVJjYnPFPa_U95I2pN9UzHRQ-LOa7YYZT808,2453
37
+ astreum/consensus/workers/validation.py,sha256=uBkZVduHtwz8hUwDf_gFDiY8TfFaoYj40jx-s-EzuEU,13358
38
+ astreum/consensus/workers/verify.py,sha256=tBBrAHH8Xcg3uopmQSjT6iuZd1s-9FkLnJ_JgeW5HdU,3423
39
+ astreum/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ astreum/crypto/chacha20poly1305.py,sha256=01VtLx_bdJC86ifQeTA494ZdKbPM2MswDTLmAs9bl8c,2479
41
+ astreum/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
42
+ astreum/crypto/quadratic_form.py,sha256=pJgbORey2NTWbQNhdyvrjy_6yjORudQ67jBz2ScHptg,4037
43
+ astreum/crypto/wesolowski.py,sha256=SUgGXW3Id07dJtWzDcs4dluIhjqbRWQ8YWjn_mK78AQ,4092
44
+ astreum/crypto/x25519.py,sha256=i29v4BmwKRcbz9E7NKqFDQyxzFtJUqN0St9jd7GS1uA,1137
45
+ astreum/machine/__init__.py,sha256=TjWf9RlGuOGbCqdjJKidh8W4pCzUoLpi3FgutssEGoQ,479
46
+ astreum/machine/parser.py,sha256=Z_Y0Sax0rPh8JcIo19-iNDQoc5GTdGQkmfFyLpCB4bw,1757
47
+ astreum/machine/tokenizer.py,sha256=6wPqR_D3h5BEvR78XKtD45ouy77RZBbz4Yh4jHSmN4o,2394
48
+ astreum/machine/evaluations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ astreum/machine/evaluations/high_evaluation.py,sha256=cqYudR9WAdVz9dURDyuQhZsuhWbmjbdw9x3UxDEYpPI,9971
50
+ astreum/machine/evaluations/low_evaluation.py,sha256=_93r6DKkCwnaOKmVGSp8JBlUPZpKrA1GECqVnwLb9es,10370
51
+ astreum/machine/evaluations/script_evaluation.py,sha256=eWouYUwTYzaqUyXqEe-lAJFIluW0gMeCDdXqle88oWw,864
52
+ astreum/machine/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ astreum/machine/models/environment.py,sha256=WjP6GRX_8e0-BAhzRLvQ6fYtKQEVR0LZi7DZNZS0TSE,1019
54
+ astreum/machine/models/expression.py,sha256=yYr9ktk-NWPL4EXwHz7ePvr9eNvfSBQe3yzRUz06yas,7675
55
+ astreum/machine/models/meter.py,sha256=5q2PFW7_jmgKVM1-vwE4RRjMfPEthUA4iu1CwR-Axws,505
56
+ astreum/storage/__init__.py,sha256=Flk6WXT2xGFHWWJiZHK3O5OpjoLTOFMqqIiJTtD58kY,111
57
+ astreum/storage/requests.py,sha256=q_rxG_k7POth93HmsUTCLSyNw-4EdFqqNExhIwm7Q0g,818
58
+ astreum/storage/setup.py,sha256=fnDZCxVskOAPDl-oTwq-iLiRCD3CKHOEgI4LALNJQWI,612
59
+ astreum/storage/actions/get.py,sha256=yf1HMYPMxRXTbZbSoe8JI6C4eWkcbScFQj-nGozBsCQ,6845
60
+ astreum/storage/actions/set.py,sha256=8MvlZS3MFvLc-apDb6mucxt1JBxw82lxMVoa0sTvdo8,5751
61
+ astreum/storage/models/atom.py,sha256=FY_bgtoju59Yo7TL1DTFTr9_pRMNBuH6-u59D6bz2fc,3163
62
+ astreum/storage/models/trie.py,sha256=Bn3ssPGI7YGS4iUH5ESvpG1NE6Ljx2Xo7wkEpQhjKUY,17587
63
+ astreum/utils/bytes.py,sha256=9QTWC2JCdwWLB5R2mPtmjPro0IUzE58DL3uEul4AheE,846
64
+ astreum/utils/config.py,sha256=jiobdNFiF44BMmoifAG3feq57ZPIhjUG4FG71cn-kgY,1527
65
+ astreum/utils/integer.py,sha256=iQt-klWOYVghu_NOT341MmHbOle4FDT3by4PNKNXscg,736
66
+ astreum/utils/logging.py,sha256=mRDtWSCj8vKt58WGKLNSkK9Oa0graNVSoS8URby4Q9g,6684
67
+ astreum-0.3.9.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
68
+ astreum-0.3.9.dist-info/METADATA,sha256=vlvV1wwS4GiKwUQhpEg3FqJ_I_5m4efioshBzwhs4bk,7766
69
+ astreum-0.3.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
+ astreum-0.3.9.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
71
+ astreum-0.3.9.dist-info/RECORD,,
@@ -1,101 +0,0 @@
1
- from enum import IntEnum
2
- from typing import Optional
3
- from cryptography.hazmat.primitives import serialization
4
- from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PublicKey
5
-
6
- class MessageTopic(IntEnum):
7
- PING = 0
8
- OBJECT_REQUEST = 1
9
- OBJECT_RESPONSE = 2
10
- ROUTE_REQUEST = 3
11
- ROUTE_RESPONSE = 4
12
- TRANSACTION = 5
13
- STORAGE_REQUEST = 6
14
-
15
-
16
- class Message:
17
- handshake: bool
18
- sender: Optional[X25519PublicKey]
19
-
20
- topic: Optional[MessageTopic]
21
- content: bytes
22
-
23
- def __init__(
24
- self,
25
- *,
26
- handshake: bool = False,
27
- sender: Optional[X25519PublicKey] = None,
28
- topic: Optional[MessageTopic] = None,
29
- content: bytes = b"",
30
- body: Optional[bytes] = None,
31
- ) -> None:
32
- if body is not None:
33
- if content and content != b"":
34
- raise ValueError("specify only one of 'content' or 'body'")
35
- content = body
36
-
37
- self.handshake = handshake
38
- self.sender = sender
39
- self.topic = topic
40
- self.content = content or b""
41
-
42
- if self.handshake:
43
- if self.sender is None:
44
- raise ValueError("handshake Message requires a sender public key")
45
- self.topic = None
46
- self.content = b""
47
- else:
48
- if self.topic is None:
49
- raise ValueError("non-handshake Message requires a topic")
50
-
51
- def to_bytes(self):
52
- if self.handshake:
53
- # handshake byte (1) + raw public key bytes
54
- return bytes([1]) + self.sender.public_bytes(
55
- encoding=serialization.Encoding.Raw,
56
- format=serialization.PublicFormat.Raw
57
- )
58
- else:
59
- # normal message: 0 + topic + content
60
- return bytes([0, self.topic.value]) + self.content
61
-
62
- @classmethod
63
- def from_bytes(cls, data: bytes) -> "Message":
64
- if len(data) < 1:
65
- raise ValueError("Cannot parse Message: no data")
66
- flag = data[0]
67
- # create empty instance
68
- msg = cls.__new__(cls)
69
-
70
- if flag == 1:
71
- # handshake message: the rest is the peer’s public key
72
- key_bytes = data[1:]
73
- if not key_bytes:
74
- raise ValueError("Handshake message missing sender public key bytes")
75
- try:
76
- sender = X25519PublicKey.from_public_bytes(key_bytes)
77
- except ValueError:
78
- raise ValueError("Invalid public key bytes")
79
- if sender is None:
80
- raise ValueError("Handshake message missing sender public key")
81
- msg.handshake = True
82
- msg.sender = sender
83
- msg.topic = None
84
- msg.content = b''
85
- elif flag == 0:
86
- # normal message: next byte is topic, rest is content
87
- if len(data) < 2:
88
- raise ValueError("Cannot parse Message: missing topic byte")
89
- topic_val = data[1]
90
- try:
91
- topic = MessageTopic(topic_val)
92
- except ValueError:
93
- raise ValueError(f"Unknown MessageTopic: {topic_val}")
94
- msg.handshake = False
95
- msg.sender = None
96
- msg.topic = topic
97
- msg.content = data[2:]
98
- else:
99
- raise ValueError(f"Invalid handshake flag: {flag}")
100
-
101
- return msg
@@ -1,23 +0,0 @@
1
- from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
2
- from cryptography.hazmat.primitives import serialization
3
- from datetime import datetime, timezone
4
- from typing import Optional, Tuple
5
-
6
- class Peer:
7
- shared_key: bytes
8
- timestamp: datetime
9
- latest_block: bytes
10
- address: Optional[Tuple[str, int]]
11
- public_key: X25519PublicKey
12
- public_key_bytes: bytes
13
-
14
- def __init__(self, my_sec_key: X25519PrivateKey, peer_pub_key: X25519PublicKey):
15
- self.shared_key = my_sec_key.exchange(peer_pub_key)
16
- self.timestamp = datetime.now(timezone.utc)
17
- self.latest_block = b""
18
- self.address = None
19
- self.public_key = peer_pub_key
20
- self.public_key_bytes = peer_pub_key.public_bytes(
21
- encoding=serialization.Encoding.Raw,
22
- format=serialization.PublicFormat.Raw,
23
- )