diff --git a/hathor/transaction/resources/create_tx.py b/hathor/transaction/resources/create_tx.py index d386cb2c7..897bd0ead 100644 --- a/hathor/transaction/resources/create_tx.py +++ b/hathor/transaction/resources/create_tx.py @@ -118,7 +118,7 @@ def _verify_unsigned_skip_pow(self, tx: Transaction) -> None: # need to run verify_inputs first to check if all inputs exist verifiers.tx.verify_inputs(tx, skip_script=True) verifiers.vertex.verify_parents(tx) - verifiers.tx.verify_sum(tx) + verifiers.tx.verify_sum(tx.get_complete_token_info()) CreateTxResource.openapi = { diff --git a/hathor/verification/token_creation_transaction_verifier.py b/hathor/verification/token_creation_transaction_verifier.py index a745aad81..66d96f111 100644 --- a/hathor/verification/token_creation_transaction_verifier.py +++ b/hathor/verification/token_creation_transaction_verifier.py @@ -15,7 +15,9 @@ from hathor.conf.settings import HathorSettings from hathor.transaction.exceptions import InvalidToken, TransactionDataError from hathor.transaction.token_creation_tx import TokenCreationTransaction +from hathor.transaction.transaction import TokenInfo from hathor.transaction.util import clean_token_string +from hathor.types import TokenUid from hathor.util import not_none @@ -25,7 +27,7 @@ class TokenCreationTransactionVerifier: def __init__(self, *, settings: HathorSettings) -> None: self._settings = settings - def verify_minted_tokens(self, tx: TokenCreationTransaction) -> None: + def verify_minted_tokens(self, tx: TokenCreationTransaction, token_dict: dict[TokenUid, TokenInfo]) -> None: """ Besides all checks made on regular transactions, a few extra ones are made: - only HTR tokens on the inputs; - new tokens are actually being minted; @@ -33,8 +35,6 @@ def verify_minted_tokens(self, tx: TokenCreationTransaction) -> None: :raises InvalidToken: when there's an error in token operations :raises InputOutputMismatch: if sum of inputs is not equal to outputs and there's no mint/melt """ - token_dict = tx.get_complete_token_info() - # make sure tokens are being minted token_info = token_dict[not_none(tx.hash)] if token_info.amount <= 0: diff --git a/hathor/verification/transaction_verifier.py b/hathor/verification/transaction_verifier.py index 5c6359b0f..630c82147 100644 --- a/hathor/verification/transaction_verifier.py +++ b/hathor/verification/transaction_verifier.py @@ -141,18 +141,6 @@ def verify_script(self, *, tx: Transaction, input_tx: TxInput, spent_tx: BaseTra except ScriptError as e: raise InvalidInputData(e) from e - def verify_sum(self, tx: Transaction) -> None: - """Verify that the sum of outputs is equal of the sum of inputs, for each token. - - If there are authority UTXOs involved, tokens can be minted or melted, so the above rule may - not be respected. - - :raises InvalidToken: when there's an error in token operations - :raises InputOutputMismatch: if sum of inputs is not equal to outputs and there's no mint/melt - """ - token_dict = tx.get_complete_token_info() - self.verify_authorities_and_deposit(token_dict) - def verify_reward_locked(self, tx: Transaction) -> None: """Will raise `RewardLocked` if any reward is spent before the best block height is enough, considering only the block rewards spent by this tx itself, and not the inherited `min_height`.""" @@ -179,7 +167,7 @@ def verify_output_token_indexes(self, tx: Transaction) -> None: if output.get_token_index() > len(tx.tokens): raise InvalidToken('token uid index not available: index {}'.format(output.get_token_index())) - def verify_authorities_and_deposit(self, token_dict: dict[TokenUid, TokenInfo]) -> None: + def verify_sum(self, token_dict: dict[TokenUid, TokenInfo]) -> None: """Verify that the sum of outputs is equal of the sum of inputs, for each token. If sum of inputs and outputs is not 0, make sure inputs have mint/melt authority. diff --git a/hathor/verification/verification_service.py b/hathor/verification/verification_service.py index 7e1100569..efa18c6f6 100644 --- a/hathor/verification/verification_service.py +++ b/hathor/verification/verification_service.py @@ -17,7 +17,9 @@ from hathor.profiler import get_cpu_profiler from hathor.transaction import BaseTransaction, Block, MergeMinedBlock, Transaction, TxVersion from hathor.transaction.token_creation_tx import TokenCreationTransaction +from hathor.transaction.transaction import TokenInfo from hathor.transaction.validation_state import ValidationState +from hathor.types import TokenUid from hathor.verification.vertex_verifiers import VertexVerifiers cpu = get_cpu_profiler() @@ -167,7 +169,13 @@ def _verify_merge_mined_block(self, block: MergeMinedBlock) -> None: self._verify_block(block) @cpu.profiler(key=lambda _, tx: 'tx-verify!{}'.format(tx.hash.hex())) - def _verify_tx(self, tx: Transaction, *, reject_locked_reward: bool) -> None: + def _verify_tx( + self, + tx: Transaction, + *, + reject_locked_reward: bool, + token_dict: dict[TokenUid, TokenInfo] | None = None + ) -> None: """ Common verification for all transactions: (i) number of inputs is at most 256 (ii) number of outputs is at most 256 @@ -186,7 +194,7 @@ def _verify_tx(self, tx: Transaction, *, reject_locked_reward: bool) -> None: self.verifiers.tx.verify_sigops_input(tx) self.verifiers.tx.verify_inputs(tx) # need to run verify_inputs first to check if all inputs exist self.verifiers.vertex.verify_parents(tx) - self.verifiers.tx.verify_sum(tx) + self.verifiers.tx.verify_sum(token_dict or tx.get_complete_token_info()) if reject_locked_reward: self.verifiers.tx.verify_reward_locked(tx) @@ -195,8 +203,9 @@ def _verify_token_creation_tx(self, tx: TokenCreationTransaction, *, reject_lock We also overload verify_sum to make some different checks """ - self._verify_tx(tx, reject_locked_reward=reject_locked_reward) - self.verifiers.token_creation_tx.verify_minted_tokens(tx) + token_dict = tx.get_complete_token_info() + self._verify_tx(tx, reject_locked_reward=reject_locked_reward, token_dict=token_dict) + self.verifiers.token_creation_tx.verify_minted_tokens(tx, token_dict) self.verifiers.token_creation_tx.verify_token_info(tx) def verify_without_storage(self, vertex: BaseTransaction) -> None: diff --git a/tests/tx/test_tx.py b/tests/tx/test_tx.py index efbb692e2..fd802c7f5 100644 --- a/tests/tx/test_tx.py +++ b/tests/tx/test_tx.py @@ -75,7 +75,7 @@ def test_input_output_match(self): _input.data = P2PKH.create_input_data(public_bytes, signature) with self.assertRaises(InputOutputMismatch): - self._verifiers.tx.verify_sum(tx) + self._verifiers.tx.verify_sum(tx.get_complete_token_info()) def test_validation(self): # add 100 blocks and check that walking through get_next_block_best_chain yields the same blocks