Skip to content

Commit 8cff879

Browse files
committed
refactor: move token info
1 parent ba246bc commit 8cff879

File tree

4 files changed

+47
-46
lines changed

4 files changed

+47
-46
lines changed

hathor/transaction/token_creation_tx.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ def to_json_extended(self) -> dict[str, Any]:
217217
return json
218218

219219
@override
220-
def get_token_info_from_inputs(self) -> dict[TokenUid, TokenInfo]:
221-
token_dict = super().get_token_info_from_inputs()
220+
def _get_token_info_from_inputs(self) -> dict[TokenUid, TokenInfo]:
221+
token_dict = super()._get_token_info_from_inputs()
222222

223223
# we add the created token's info to token_dict, as the creation tx allows for mint/melt
224224
assert self.hash is not None

hathor/transaction/transaction.py

+42-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from hathor.profiler import get_cpu_profiler
2323
from hathor.transaction import BaseTransaction, Block, TxInput, TxOutput, TxVersion
2424
from hathor.transaction.base_transaction import TX_HASH_SIZE
25+
from hathor.transaction.exceptions import InvalidToken
2526
from hathor.transaction.util import VerboseCallback, unpack, unpack_len
2627
from hathor.types import TokenUid, VertexId
2728
from hathor.util import not_none
@@ -278,7 +279,16 @@ def verify_checkpoint(self, checkpoints: list[Checkpoint]) -> None:
278279
raise InvalidNewTransaction(f'Invalid new transaction {self.hash_hex}: expected to reach a checkpoint but '
279280
'none of its children is checkpoint-valid')
280281

281-
def get_token_info_from_inputs(self) -> dict[TokenUid, TokenInfo]:
282+
def get_complete_token_info(self) -> dict[TokenUid, TokenInfo]:
283+
"""
284+
Get a complete token info dict, including data from both inputs and outputs.
285+
"""
286+
token_dict = self._get_token_info_from_inputs()
287+
self._update_token_info_from_outputs(token_dict=token_dict)
288+
289+
return token_dict
290+
291+
def _get_token_info_from_inputs(self) -> dict[TokenUid, TokenInfo]:
282292
"""Sum up all tokens present in the inputs and their properties (amount, can_mint, can_melt)
283293
"""
284294
token_dict: dict[TokenUid, TokenInfo] = {}
@@ -305,6 +315,37 @@ def get_token_info_from_inputs(self) -> dict[TokenUid, TokenInfo]:
305315

306316
return token_dict
307317

318+
def _update_token_info_from_outputs(self, *, token_dict: dict[TokenUid, TokenInfo]) -> None:
319+
"""Iterate over the outputs and add values to token info dict. Updates the dict in-place.
320+
321+
Also, checks if no token has authorities on the outputs not present on the inputs
322+
323+
:raises InvalidToken: when there's an error in token operations
324+
"""
325+
# iterate over outputs and add values to token_dict
326+
for index, tx_output in enumerate(self.outputs):
327+
token_uid = self.get_token_uid(tx_output.get_token_index())
328+
token_info = token_dict.get(token_uid)
329+
if token_info is None:
330+
raise InvalidToken('no inputs for token {}'.format(token_uid.hex()))
331+
else:
332+
# for authority outputs, make sure the same capability (mint/melt) was present in the inputs
333+
if tx_output.can_mint_token() and not token_info.can_mint:
334+
raise InvalidToken('output has mint authority, but no input has it: {}'.format(
335+
tx_output.to_human_readable()))
336+
if tx_output.can_melt_token() and not token_info.can_melt:
337+
raise InvalidToken('output has melt authority, but no input has it: {}'.format(
338+
tx_output.to_human_readable()))
339+
340+
if tx_output.is_token_authority():
341+
# make sure we only have authorities that we know of
342+
if tx_output.value > TxOutput.ALL_AUTHORITIES:
343+
raise InvalidToken('Invalid authorities in output (0b{0:b})'.format(tx_output.value))
344+
else:
345+
# for regular outputs, just subtract from the total amount
346+
sum_tokens = token_info.amount + tx_output.value
347+
token_dict[token_uid] = TokenInfo(sum_tokens, token_info.can_mint, token_info.can_melt)
348+
308349
def iter_spent_rewards(self) -> Iterator[Block]:
309350
"""Iterate over all the rewards being spent, assumes tx has been verified."""
310351
for input_tx in self.inputs:

hathor/verification/token_creation_transaction_verifier.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def verify_sum(self, tx: Transaction) -> None:
4040
:raises InputOutputMismatch: if sum of inputs is not equal to outputs and there's no mint/melt
4141
"""
4242
assert isinstance(tx, TokenCreationTransaction)
43-
token_dict = self.get_complete_token_info(tx)
43+
token_dict = tx.get_complete_token_info()
4444

4545
# make sure tokens are being minted
4646
token_info = token_dict[not_none(tx.hash)]

hathor/verification/transaction_verifier.py

+2-42
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
from hathor.profiler import get_cpu_profiler
16-
from hathor.transaction import BaseTransaction, Transaction, TxInput, TxOutput
16+
from hathor.transaction import BaseTransaction, Transaction, TxInput
1717
from hathor.transaction.exceptions import (
1818
ConflictingInputs,
1919
DuplicatedParents,
@@ -186,7 +186,7 @@ def verify_sum(self, tx: Transaction) -> None:
186186
:raises InvalidToken: when there's an error in token operations
187187
:raises InputOutputMismatch: if sum of inputs is not equal to outputs and there's no mint/melt
188188
"""
189-
token_dict = self.get_complete_token_info(tx)
189+
token_dict = tx.get_complete_token_info()
190190
self.verify_authorities_and_deposit(token_dict)
191191

192192
def verify_reward_locked(self, tx: Transaction) -> None:
@@ -258,43 +258,3 @@ def verify_authorities_and_deposit(self, token_dict: dict[TokenUid, TokenInfo])
258258
htr_info.amount,
259259
htr_expected_amount,
260260
))
261-
262-
def update_token_info_from_outputs(self, tx: Transaction, *, token_dict: dict[TokenUid, TokenInfo]) -> None:
263-
"""Iterate over the outputs and add values to token info dict. Updates the dict in-place.
264-
265-
Also, checks if no token has authorities on the outputs not present on the inputs
266-
267-
:raises InvalidToken: when there's an error in token operations
268-
"""
269-
# iterate over outputs and add values to token_dict
270-
for index, tx_output in enumerate(tx.outputs):
271-
token_uid = tx.get_token_uid(tx_output.get_token_index())
272-
token_info = token_dict.get(token_uid)
273-
if token_info is None:
274-
raise InvalidToken('no inputs for token {}'.format(token_uid.hex()))
275-
else:
276-
# for authority outputs, make sure the same capability (mint/melt) was present in the inputs
277-
if tx_output.can_mint_token() and not token_info.can_mint:
278-
raise InvalidToken('output has mint authority, but no input has it: {}'.format(
279-
tx_output.to_human_readable()))
280-
if tx_output.can_melt_token() and not token_info.can_melt:
281-
raise InvalidToken('output has melt authority, but no input has it: {}'.format(
282-
tx_output.to_human_readable()))
283-
284-
if tx_output.is_token_authority():
285-
# make sure we only have authorities that we know of
286-
if tx_output.value > TxOutput.ALL_AUTHORITIES:
287-
raise InvalidToken('Invalid authorities in output (0b{0:b})'.format(tx_output.value))
288-
else:
289-
# for regular outputs, just subtract from the total amount
290-
sum_tokens = token_info.amount + tx_output.value
291-
token_dict[token_uid] = TokenInfo(sum_tokens, token_info.can_mint, token_info.can_melt)
292-
293-
def get_complete_token_info(self, tx: Transaction) -> dict[TokenUid, TokenInfo]:
294-
"""
295-
Get a complete token info dict, including data from both inputs and outputs.
296-
"""
297-
token_dict = tx.get_token_info_from_inputs()
298-
self.update_token_info_from_outputs(tx, token_dict=token_dict)
299-
300-
return token_dict

0 commit comments

Comments
 (0)