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

@@ -0,0 +1,30 @@
1
+ class Block:
2
+ @classmethod
3
+ def from_bytes(cls, validator) -> 'Block':
4
+ """
5
+ Deserialize an Account from its byte representation.
6
+
7
+ Expected format: [balance, code, counter, data]
8
+
9
+ The public_key (and optional secret_key) must be provided separately.
10
+ """
11
+ decoded = bytes_format.decode(data)
12
+ balance, code, counter, account_data = decoded
13
+ return cls(public_key, balance, code, counter, account_data, secret_key=secret_key)
14
+
15
+ def to_bytes(self) -> bytes:
16
+ """
17
+ Serialize the Account into bytes.
18
+
19
+ Format: [balance, code, counter, data]
20
+ """
21
+ return bytes_format.encode([
22
+ self.balance,
23
+ self.code,
24
+ self.counter,
25
+ self.data
26
+ ])
27
+
28
+ class Chain:
29
+ def __init__(self, latest_block: Block):
30
+ self.latest_block = latest_block
@@ -0,0 +1,146 @@
1
+ from typing import Optional
2
+ import time
3
+ from .account import Account, get_account_from_storage
4
+ import astreum.utils.bytes_format as bytes_format
5
+
6
+ class Transaction:
7
+ def __init__(
8
+ self,
9
+ sender: Account,
10
+ recipient: Account,
11
+ amount: int,
12
+ data: bytes = None,
13
+ counter: int = 0
14
+ ):
15
+ self.sender = sender
16
+ self.recipient = recipient
17
+ self.amount = amount
18
+ self.data = data
19
+ self.counter = counter
20
+ self.timestamp = time.time()
21
+ self.signature = None
22
+
23
+ @classmethod
24
+ def from_bytes(cls, data: bytes, resolve_accounts: bool = False, accounts=None, storage=None) -> 'Transaction':
25
+ """
26
+ Deserialize a Transaction from its byte representation.
27
+
28
+ Expected format: [sender_hash, recipient_hash, amount, data, counter, timestamp, signature]
29
+
30
+ Args:
31
+ data: Serialized transaction data
32
+ resolve_accounts: If True, attempts to resolve account objects from storage
33
+ accounts: Accounts instance (required if resolve_accounts is True)
34
+ storage: Storage instance (required if resolve_accounts is True)
35
+
36
+ Returns:
37
+ Transaction object
38
+ """
39
+ decoded = bytes_format.decode(data)
40
+ sender_public_key, recipient_public_key, amount, tx_data, counter, timestamp, signature = decoded
41
+
42
+ sender_account = None
43
+ recipient_account = None
44
+
45
+ if resolve_accounts:
46
+ if accounts is None or storage is None:
47
+ raise ValueError("Both accounts and storage must be provided when resolve_accounts is True")
48
+ sender_account = get_account_from_storage(sender_public_key, accounts, storage)
49
+ recipient_account = get_account_from_storage(recipient_public_key, accounts, storage)
50
+ else:
51
+ # Create minimal Account objects with just the public keys
52
+ sender_account = Account(sender_public_key, 0, b'', 0, b'')
53
+ recipient_account = Account(recipient_public_key, 0, b'', 0, b'')
54
+
55
+ transaction = cls(sender_account, recipient_account, amount, tx_data, counter)
56
+ transaction.timestamp = timestamp
57
+ transaction.signature = signature
58
+ return transaction
59
+
60
+ def to_bytes(self) -> bytes:
61
+ """
62
+ Serialize the Transaction into bytes.
63
+
64
+ Format: [sender_hash, recipient_hash, amount, data, counter, timestamp, signature]
65
+ """
66
+ return bytes_format.encode([
67
+ self.sender.public_key,
68
+ self.recipient.public_key,
69
+ self.amount,
70
+ self.data,
71
+ self.counter,
72
+ self.timestamp,
73
+ self.signature
74
+ ])
75
+
76
+
77
+ def get_tx_from_storage(hash: bytes) -> Optional[Transaction]:
78
+ """Resolves storage objects to get a transaction.
79
+
80
+ Args:
81
+ hash: Hash of the transaction and merkle root of the transaction
82
+
83
+ Returns:
84
+ Transaction object if found, None otherwise
85
+ """
86
+ return None
87
+
88
+
89
+ def put_tx_to_storage(transaction: Transaction):
90
+ """Puts a transaction into storage.
91
+
92
+ Args:
93
+ transaction: Transaction object to put into storage
94
+
95
+ Returns:
96
+ None
97
+ """
98
+ return None
99
+
100
+
101
+ def get_tx_hash(transaction: Transaction) -> bytes:
102
+ """Get the hash of a transaction.
103
+
104
+ Args:
105
+ transaction: Transaction object to get hash for
106
+
107
+ Returns:
108
+ Merkle root of the transaction body hash and signature
109
+ """
110
+ return hash_data(get_tx_body_hash(transaction) + hash_data(transaction.signature))
111
+
112
+ def get_tx_body_hash(transaction: Transaction) -> bytes:
113
+ """Get the hash of the transaction body.
114
+
115
+ Args:
116
+ transaction: Transaction object to get hash for
117
+
118
+ Returns:
119
+ Hash of the transaction body
120
+ """
121
+ return hash_data(transaction)
122
+
123
+ def sign_tx(transaction: Transaction, private_key: bytes) -> Transaction:
124
+ """Sign a transaction.
125
+
126
+ Args:
127
+ transaction: Transaction object to sign
128
+ private_key: Private key to sign with
129
+
130
+ Returns:
131
+ Signed transaction
132
+ """
133
+ transaction.signature = hash_data(get_tx_body_hash(transaction) + private_key)
134
+ return transaction
135
+
136
+
137
+ def verify_tx(transaction: Transaction) -> bool:
138
+ """Verify a transaction.
139
+
140
+ Args:
141
+ transaction: Transaction object to verify,with sender public key
142
+
143
+ Returns:
144
+ True if the transaction is valid, False otherwise
145
+ """
146
+ return True
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: astreum
3
- Version: 0.1.15
3
+ Version: 0.1.17
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
@@ -14,6 +14,7 @@ License-File: LICENSE
14
14
  Requires-Dist: pycryptodomex==3.21.0
15
15
  Requires-Dist: cryptography==44.0.2
16
16
  Requires-Dist: blake3==1.0.4
17
+ Dynamic: license-file
17
18
 
18
19
  # lib
19
20
 
@@ -23,31 +23,36 @@ astreum/machine/environment.py,sha256=K0084U6B7wwjrDZ9b2_7cEcbBzsB7UOy_Zpbrr7B3G
23
23
  astreum/machine/error.py,sha256=MvqBaZZt33rNELNhUJ2lER3TE3aS8WVqsWF2hz2AwoA,38
24
24
  astreum/node/__init__.py,sha256=K7F21c7V9vlJuTWoSw9arsLA8RF5KNR5I6QS3Frl_Ys,19481
25
25
  astreum/node/utils.py,sha256=amGhNYHVMjvAO-9vBRAcim-S5LlLSRudqooBN-XPdm4,702
26
- astreum/node/relay/__init__.py,sha256=0zvbchIbLUPqGA7QXJbXokKupcIq6Iu3X3VUpxejIQc,14981
26
+ astreum/node/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ astreum/node/crypto/ed25519.py,sha256=FRnvlN0kZlxn4j-sJKl-C9tqiz_0z4LZyXLj3KIj1TQ,1760
28
+ astreum/node/crypto/x25519.py,sha256=i29v4BmwKRcbz9E7NKqFDQyxzFtJUqN0St9jd7GS1uA,1137
29
+ astreum/node/relay/__init__.py,sha256=A6br8QSGLW7qmKYBJNIC4bEf5QMzLBFaa_FH3MaOJrs,15069
27
30
  astreum/node/relay/bucket.py,sha256=pcmollbbM-xeHlmDxLZnzvf0Ut-9v9RoN6SijYiQuu8,2893
28
31
  astreum/node/relay/envelope.py,sha256=sDKsIvJruQKLWgWs92sx1mCjMHF7yQVoLguPygw2Pz8,10037
29
32
  astreum/node/relay/message.py,sha256=uezmGjNaQK4fZmYQLCHd2YpiosaaFb8DOa3H58HS1jA,2887
30
33
  astreum/node/relay/peer.py,sha256=DlvTR9j0BZQ1dW-p_9UGgfLvQqwNdpNLMSCYEW4FhyI,5899
31
34
  astreum/node/relay/route.py,sha256=fyOSsAe1mfsCVeN6LtQ_OEUEb1FiC5dobZBEJKNGU9U,5814
32
35
  astreum/node/storage/__init__.py,sha256=eJL7ILUGKSKDhXZqkn3Rk5TUza39vIcwPwAW_AaIHTk,326
33
- astreum/node/storage/merkle.py,sha256=gZf18ZhaJffckmuQbc92MwfxepBLwINdORuM6EeyJBc,23879
36
+ astreum/node/storage/merkle.py,sha256=sC7gfxPDUBgv3iiFs5PyxPgYbC4CoE-If5TQvkuoTGU,10295
37
+ astreum/node/storage/patricia.py,sha256=zP4whShdB7yOFcEPLE1-1PIFfx_LdK8DyMSadnF0KT0,11588
34
38
  astreum/node/storage/storage.py,sha256=czJDhRK2rQxjOo88fhZ6j10f55RW8hWp1qq7c4yur6Y,10086
35
- astreum/node/storage/trie.py,sha256=DrYNEgTS6j7WL-LtVzzCIDjSmjphjV-jL1bGXBlcyfQ,4930
36
39
  astreum/node/storage/utils.py,sha256=CxKH9GbW31aVYs2Hwg1SirCykSnH_3_JisEayDrpOvY,5169
37
40
  astreum/node/validation/__init__.py,sha256=D9Gmc5x5V5xgXtM32axuDMSzgKiDCz7MiUShNnuFKYc,1636
38
- astreum/node/validation/account.py,sha256=gFoJHoSAZs7BKGaewNaLiziivKINTCh8MBpOoN-YajA,27951
41
+ astreum/node/validation/account.py,sha256=mKbJSi3sfQ5K9a4zwgdyPGqT3gXHekI55yDDVpzcolo,3650
42
+ astreum/node/validation/block.py,sha256=ff4ZvMtIBuoY232SHxtRiwU3J-ku_hQOiqssHhIqbXY,934
39
43
  astreum/node/validation/constants.py,sha256=ImIdLZFtMKx1iWg60YssEKl2tdDqZQnIa2JaJE6CX0o,422
40
44
  astreum/node/validation/stake.py,sha256=Z9EPM-X9c92fpsZIYsdVpvgz4DhxQViPM-RDktWUZq8,7141
41
45
  astreum/node/validation/state.py,sha256=QMXY7h4da-o79wMjJW93ixtepyhgcbJEf101yVuZurg,7661
46
+ astreum/node/validation/transaction.py,sha256=Lovx1CWIxL45glFU-LBDxI1argBLxSmDAcg1TteaOlY,4701
42
47
  astreum/node/validation/vdf.py,sha256=HDdnqn9O_LicfE7SNCmncawKoR-ojLyjlpn74OvRNOU,2194
43
- astreum/node/validation/block/__init__.py,sha256=n2HaMG_5cpa7y5xko-c7vbHz8rL-1wAGthmr8boNrCs,216
44
- astreum/node/validation/block/create.py,sha256=apD9h92b9Y146zeppSzKNk_NJPgyBy7FhxoEkypQQNk,2515
45
- astreum/node/validation/block/model.py,sha256=d7x3_tX2MPLnGODL_5_vNjQfLdYa405blc-zL9o8HFA,2589
46
- astreum/node/validation/block/validate.py,sha256=niLexCNhEwUJLclyrdNZSvHcVa_J6jlu7J3FiWY7XBU,6232
48
+ astreum/node/validation/_block/__init__.py,sha256=n2HaMG_5cpa7y5xko-c7vbHz8rL-1wAGthmr8boNrCs,216
49
+ astreum/node/validation/_block/create.py,sha256=apD9h92b9Y146zeppSzKNk_NJPgyBy7FhxoEkypQQNk,2515
50
+ astreum/node/validation/_block/model.py,sha256=d7x3_tX2MPLnGODL_5_vNjQfLdYa405blc-zL9o8HFA,2589
51
+ astreum/node/validation/_block/validate.py,sha256=niLexCNhEwUJLclyrdNZSvHcVa_J6jlu7J3FiWY7XBU,6232
47
52
  astreum/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
53
  astreum/utils/bytes_format.py,sha256=X4tG5GGPweNCE54bHYkLFiuLTbmpy5upO_s1Cef-MGA,2711
49
- astreum-0.1.15.dist-info/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
50
- astreum-0.1.15.dist-info/METADATA,sha256=dkXfuFNHZTgGlPpIHmcYC8hReofWF52gD_4_6JcCQSA,3290
51
- astreum-0.1.15.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
52
- astreum-0.1.15.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
53
- astreum-0.1.15.dist-info/RECORD,,
54
+ astreum-0.1.17.dist-info/licenses/LICENSE,sha256=gYBvRDP-cPLmTyJhvZ346QkrYW_eleke4Z2Yyyu43eQ,1089
55
+ astreum-0.1.17.dist-info/METADATA,sha256=0cJVTCBktTFF2gwVAFuxDeIvojUr3pA7SeCbNCP4VuE,3312
56
+ astreum-0.1.17.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
57
+ astreum-0.1.17.dist-info/top_level.txt,sha256=1EG1GmkOk3NPmUA98FZNdKouhRyget-KiFiMk0i2Uz0,8
58
+ astreum-0.1.17.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (79.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,146 +0,0 @@
1
- from astreum.utils.bytes_format import encode, decode
2
- from astreum.utils.hash import hash_data
3
- from typing import Optional, List
4
- from ..storage import Storage
5
-
6
-
7
- class Trie:
8
- def __init__(self, root: TrieNode, storage: Storage):
9
- self.root = root
10
- self.storage = storage
11
-
12
- def insert(self, key: bytes, data: bytes):
13
- self.root = self._insert(self.root, key, data)
14
-
15
- def _insert(self, node: TrieNode, key: bytes, data: bytes) -> TrieNode:
16
- if node is None:
17
- return TrieNode(key, data)
18
- if key < node.key:
19
- node.children = self._insert(node.children, key, data)
20
- elif key > node.key:
21
- node.children = self._insert(node.children, key, data)
22
- else:
23
- node.data = data
24
- return node
25
-
26
- def lookup(self, key: bytes) -> bytes:
27
- """
28
- Look up a key in the trie.
29
-
30
- Args:
31
- key: The key to look up
32
-
33
- Returns:
34
- The data associated with the key, or None if not found
35
- """
36
- return self._lookup(self.root, key)
37
-
38
- def _lookup(self, node: Optional[TrieNode], key: bytes) -> bytes:
39
- """
40
- Recursive helper for looking up a key in the trie.
41
-
42
- Args:
43
- node: The current node being examined
44
- key: The key to look up
45
-
46
- Returns:
47
- The data associated with the key, or None if not found
48
- """
49
- if node is None:
50
- return None
51
-
52
- # If we found an exact match, return the data
53
- if node.key == key:
54
- return node.data
55
-
56
- # Make sure node has a storage reference
57
- if node.storage is None:
58
- node.storage = self.storage
59
-
60
- # Use child_lookup to find the most promising child
61
- child_node = node.child_lookup(key)
62
- if child_node is None:
63
- return None
64
-
65
- # Create and traverse to the child node
66
- child_node = TrieNode.from_bytes(child_data, self.storage)
67
- return self._lookup(child_node, key)
68
-
69
- class TrieNode:
70
- """
71
- A node in a trie.
72
-
73
- Attributes:
74
- key: The key of the node
75
- data: The data stored in the node
76
- children: The children of the node
77
- storage: Reference to storage service (not serialized)
78
- """
79
- def __init__(self, key: bytes, data: bytes = None, children: bytes = None, storage = None):
80
- """
81
- Initialize a new TrieNode.
82
-
83
- Args:
84
- key: The key of the node
85
- data: The data stored in the node
86
- children: a byte string of children hashes each are 32 bytes long
87
- storage: Storage instance for retrieving child nodes (not serialized)
88
- """
89
- self.key = key
90
- self.data = data
91
- self.children = children
92
- self.storage = storage
93
-
94
- def to_bytes(self) -> bytes:
95
- """Serialize the node data (excluding storage reference)"""
96
- return encode([self.key, self.data, self.children])
97
-
98
- @classmethod
99
- def from_bytes(cls, data: bytes, storage = None) -> 'TrieNode':
100
- """
101
- Deserialize node data and optionally attach a storage reference.
102
-
103
- Args:
104
- data: The serialized node data
105
- storage: Optional storage instance to attach to the node
106
-
107
- Returns:
108
- A new TrieNode instance
109
- """
110
- key, data, children = decode(data)
111
- return TrieNode(key, data, children, storage)
112
-
113
- def hash(self) -> bytes:
114
- return hash_data(self.to_bytes())
115
-
116
- def child_lookup(self, key: bytes) -> Optional[TrieNode]:
117
- """
118
- Does a binary lookup of the keys in the children of this node.
119
- Uses storage to look up children and finds a starting match for the key.
120
- """
121
- if self.children is None or self.storage is None:
122
- return None
123
-
124
- # Parse children bytes into a list of 32-byte hashes
125
- children_hashes = []
126
- for i in range(0, len(self.children), 32):
127
- if i + 32 <= len(self.children):
128
- children_hashes.append(self.children[i:i+32])
129
-
130
- # Look up each child in storage and compare keys
131
- for child_hash in children_hashes:
132
- # Get child node data from storage
133
- child_data = self.storage.get(child_hash)
134
- if child_data is None:
135
- continue # Skip if not found in storage
136
-
137
- # Deserialize the child node
138
- child_node = TrieNode.from_bytes(child_data, self.storage)
139
-
140
- # Check if this child's key is a prefix of the lookup key
141
- # or if the lookup key is a prefix of this child's key
142
- min_len = min(len(child_node.key), len(key))
143
- if child_node.key[:min_len] == key[:min_len]:
144
- return child_node
145
-
146
- return None
File without changes
File without changes
File without changes
File without changes