diff --git a/hathor/cli/db_import.py b/hathor/cli/db_import.py index 8063b31d20..2edde2f392 100644 --- a/hathor/cli/db_import.py +++ b/hathor/cli/db_import.py @@ -90,7 +90,7 @@ def _import_txs(self) -> Iterator['BaseTransaction']: tx = parser.deserialize(tx_bytes) assert tx is not None tx.storage = self.tx_storage - self.manager.on_new_tx(tx, quiet=True, fails_silently=False) + self.manager.on_new_tx(tx, quiet=True) yield tx diff --git a/hathor/cli/events_simulator/scenario.py b/hathor/cli/events_simulator/scenario.py index 7ee5b79170..f497b307a5 100644 --- a/hathor/cli/events_simulator/scenario.py +++ b/hathor/cli/events_simulator/scenario.py @@ -71,13 +71,13 @@ def simulate_single_chain_blocks_and_transactions(simulator: 'Simulator', manage tx = gen_new_tx(manager, address, 1000) tx.weight = manager.daa.minimum_tx_weight(tx) tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) simulator.run(60) tx = gen_new_tx(manager, address, 2000) tx.weight = manager.daa.minimum_tx_weight(tx) tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) simulator.run(60) add_new_blocks(manager, 1) @@ -117,7 +117,7 @@ def simulate_unvoided_transaction(simulator: 'Simulator', manager: 'HathorManage tx = gen_new_tx(manager, address, 1000) tx.weight = 19.0005 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) simulator.run(60) # A clone is created with a greater timestamp and a lower weight. It's a voided twin tx. @@ -125,7 +125,7 @@ def simulate_unvoided_transaction(simulator: 'Simulator', manager: 'HathorManage tx2.timestamp += 60 tx2.weight = 19 tx2.update_hash() - assert manager.propagate_tx(tx2, fails_silently=False) + assert manager.propagate_tx(tx2) simulator.run(60) # Only the second tx is voided @@ -140,7 +140,7 @@ def simulate_unvoided_transaction(simulator: 'Simulator', manager: 'HathorManage tx2.hash, ] block.update_hash() - assert manager.propagate_tx(block, fails_silently=False) + assert manager.propagate_tx(block) simulator.run(60) # The first tx gets voided and the second gets unvoided @@ -165,7 +165,7 @@ def simulate_invalid_mempool_transaction(simulator: 'Simulator', manager: 'Hatho tx = gen_new_tx(manager, address, 1000) tx.weight = manager.daa.minimum_tx_weight(tx) tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) simulator.run(60) balance_per_address = manager.wallet.get_balance_per_address(settings.HATHOR_TOKEN_UID) assert balance_per_address[address] == 1000 @@ -176,7 +176,7 @@ def simulate_invalid_mempool_transaction(simulator: 'Simulator', manager: 'Hatho b0: Block = tb0.generate_mining_block(manager.rng, storage=manager.tx_storage) b0.weight = 10 manager.cpu_mining_service.resolve(b0) - assert manager.propagate_tx(b0, fails_silently=False) + assert manager.propagate_tx(b0) simulator.run(60) # the transaction should have been removed from the mempool and the storage after the re-org @@ -204,7 +204,7 @@ def simulate_empty_script(simulator: 'Simulator', manager: 'HathorManager') -> N tx1.outputs[1].script = b'' tx1.weight = manager.daa.minimum_tx_weight(tx1) tx1.update_hash() - assert manager.propagate_tx(tx1, fails_silently=False) + assert manager.propagate_tx(tx1) simulator.run(60) tx2 = gen_new_tx(manager, address, 1000) @@ -212,7 +212,7 @@ def simulate_empty_script(simulator: 'Simulator', manager: 'HathorManager') -> N tx2.outputs = [TxOutput(value=1000, script=original_script)] tx2.weight = manager.daa.minimum_tx_weight(tx2) tx2.update_hash() - assert manager.propagate_tx(tx2, fails_silently=False) + assert manager.propagate_tx(tx2) simulator.run(60) add_new_blocks(manager, 1) @@ -242,7 +242,7 @@ def simulate_custom_script(simulator: 'Simulator', manager: 'HathorManager') -> tx1.outputs[1].script = s.data tx1.weight = manager.daa.minimum_tx_weight(tx1) tx1.update_hash() - assert manager.propagate_tx(tx1, fails_silently=False) + assert manager.propagate_tx(tx1) simulator.run(60) tx2 = gen_new_tx(manager, address, 1000) @@ -250,7 +250,7 @@ def simulate_custom_script(simulator: 'Simulator', manager: 'HathorManager') -> tx2.outputs = [TxOutput(value=1000, script=original_script)] tx2.weight = manager.daa.minimum_tx_weight(tx2) tx2.update_hash() - assert manager.propagate_tx(tx2, fails_silently=False) + assert manager.propagate_tx(tx2) simulator.run(60) add_new_blocks(manager, 1) diff --git a/hathor/consensus/poa/poa_block_producer.py b/hathor/consensus/poa/poa_block_producer.py index a117582462..60f7c9269e 100644 --- a/hathor/consensus/poa/poa_block_producer.py +++ b/hathor/consensus/poa/poa_block_producer.py @@ -193,7 +193,7 @@ def _produce_block(self, previous_block: PoaBlock) -> None: parent=block.get_block_parent_hash().hex(), voided=bool(block.get_metadata().voided_by), ) - self.manager.on_new_tx(block, propagate_to_peers=True, fails_silently=False) + self.manager.on_new_tx(block, propagate_to_peers=True) def _expected_block_timestamp(self, previous_block: Block, signer_index: int) -> int: """Calculate the expected timestamp for a new block.""" diff --git a/hathor/dag_builder/artifacts.py b/hathor/dag_builder/artifacts.py index cc990893c5..29fb1d3679 100644 --- a/hathor/dag_builder/artifacts.py +++ b/hathor/dag_builder/artifacts.py @@ -63,7 +63,7 @@ def propagate_with(self, manager: HathorManager, *, up_to: str | None = None) -> for node, vertex in self.list: if found_begin: - assert manager.on_new_tx(vertex, fails_silently=False) + assert manager.on_new_tx(vertex) self._last_propagated = node.name if node.name == self._last_propagated: diff --git a/hathor/manager.py b/hathor/manager.py index b44407eb0b..4c247f9c04 100644 --- a/hathor/manager.py +++ b/hathor/manager.py @@ -707,7 +707,7 @@ def get_tokens_issued_per_block(self, height: int) -> int: """Return the number of tokens issued (aka reward) per block of a given height.""" return self.daa.get_tokens_issued_per_block(height) - def submit_block(self, blk: Block, fails_silently: bool = True) -> bool: + def submit_block(self, blk: Block) -> bool: """Used by submit block from all mining APIs. """ tips = self.tx_storage.get_best_block_tips() @@ -724,7 +724,7 @@ def submit_block(self, blk: Block, fails_silently: bool = True) -> bool: ) if blk.weight <= min_insignificant_weight: self.log.warn('submit_block(): insignificant weight? accepted anyway', blk=blk.hash_hex, weight=blk.weight) - return self.propagate_tx(blk, fails_silently=fails_silently) + return self.propagate_tx(blk) def push_tx(self, tx: Transaction, allow_non_standard_script: bool = False, max_output_script_size: int | None = None) -> None: @@ -755,9 +755,9 @@ def push_tx(self, tx: Transaction, allow_non_standard_script: bool = False, if not tx_from_lib.is_standard(max_output_script_size, not allow_non_standard_script): raise NonStandardTxError('Transaction is non standard.') - self.propagate_tx(tx, fails_silently=False) + self.propagate_tx(tx) - def propagate_tx(self, tx: BaseTransaction, fails_silently: bool = True) -> bool: + def propagate_tx(self, tx: BaseTransaction) -> bool: """Push a new transaction to the network. It is used by both the wallet and the mining modules. :return: True if the transaction was accepted @@ -768,14 +768,13 @@ def propagate_tx(self, tx: BaseTransaction, fails_silently: bool = True) -> bool else: tx.storage = self.tx_storage - return self.on_new_tx(tx, fails_silently=fails_silently, propagate_to_peers=True) + return self.on_new_tx(tx, propagate_to_peers=True) def on_new_tx( self, - tx: BaseTransaction, + vertex: BaseTransaction, *, quiet: bool = False, - fails_silently: bool = True, propagate_to_peers: bool = True, reject_locked_reward: bool = True ) -> bool: @@ -783,18 +782,12 @@ def on_new_tx( :param tx: transaction to be added :param quiet: if True will not log when a new tx is accepted - :param fails_silently: if False will raise an exception when tx cannot be added :param propagate_to_peers: if True will relay the tx to other peers if it is accepted """ - success = self.vertex_handler.on_new_vertex( - tx, - quiet=quiet, - fails_silently=fails_silently, - reject_locked_reward=reject_locked_reward, - ) + success = self.vertex_handler.on_new_relayed_vertex(vertex, reject_locked_reward=reject_locked_reward) if propagate_to_peers and success: - self.connections.send_tx_to_peers(tx) + self.connections.send_tx_to_peers(vertex) return success diff --git a/hathor/p2p/sync_v2/agent.py b/hathor/p2p/sync_v2/agent.py index d96fd91e45..eca0d2a337 100644 --- a/hathor/p2p/sync_v2/agent.py +++ b/hathor/p2p/sync_v2/agent.py @@ -22,7 +22,7 @@ from structlog import get_logger from twisted.internet.defer import Deferred, inlineCallbacks -from twisted.internet.task import LoopingCall, deferLater +from twisted.internet.task import LoopingCall from hathor.conf.settings import HathorSettings from hathor.exception import InvalidNewTransaction @@ -613,17 +613,11 @@ def find_best_common_block(self, return lo @inlineCallbacks - def on_block_complete(self, blk: Block, vertex_list: list[BaseTransaction]) -> Generator[Any, Any, None]: + def on_block_complete(self, blk: Block, vertex_list: list[Transaction]) -> Generator[Any, Any, None]: """This method is called when a block and its transactions are downloaded.""" # Note: Any vertex and block could have already been added by another concurrent syncing peer. try: - for tx in vertex_list: - if not self.tx_storage.transaction_exists(tx.hash): - self.vertex_handler.on_new_vertex(tx, fails_silently=False) - yield deferLater(self.reactor, 0, lambda: None) - - if not self.tx_storage.transaction_exists(blk.hash): - self.vertex_handler.on_new_vertex(blk, fails_silently=False) + yield self.vertex_handler.on_new_block(blk, deps=vertex_list) except InvalidNewTransaction: self.protocol.send_error_and_close_connection('invalid vertex received') @@ -1038,6 +1032,7 @@ def handle_transaction(self, payload: str) -> None: tx.storage = self.tx_storage assert self._tx_streaming_client is not None + assert isinstance(tx, Transaction) self._tx_streaming_client.handle_transaction(tx) @inlineCallbacks @@ -1166,17 +1161,18 @@ def handle_data(self, payload: str) -> None: # XXX: maybe we could add a hash blacklist and punish peers propagating known bad txs self.tx_storage.compare_bytes_with_local_tx(tx) return - else: - # If we have not requested the data, it is a new transaction being propagated - # in the network, thus, we propagate it as well. - if self.tx_storage.can_validate_full(tx): - self.log.debug('tx received in real time from peer', tx=tx.hash_hex, peer=self.protocol.get_peer_id()) - try: - success = self.vertex_handler.on_new_vertex(tx, fails_silently=False) - if success: - self.protocol.connections.send_tx_to_peers(tx) - except InvalidNewTransaction: - self.protocol.send_error_and_close_connection('invalid vertex received') - else: - self.log.debug('skipping tx received in real time from peer', - tx=tx.hash_hex, peer=self.protocol.get_peer_id()) + + # Unsolicited vertices must be fully validated. + if not self.tx_storage.can_validate_full(tx): + self.log.debug('skipping tx received in real time from peer', + tx=tx.hash_hex, peer=self.protocol.get_peer_id()) + return + + # Finally, it is either an unsolicited new transaction or block. + self.log.debug('tx received in real time from peer', tx=tx.hash_hex, peer=self.protocol.get_peer_id()) + try: + success = self.vertex_handler.on_new_relayed_vertex(tx) + if success: + self.protocol.connections.send_tx_to_peers(tx) + except InvalidNewTransaction: + self.protocol.send_error_and_close_connection('invalid vertex received') diff --git a/hathor/p2p/sync_v2/blockchain_streaming_client.py b/hathor/p2p/sync_v2/blockchain_streaming_client.py index e78ec056bc..295e59c7e5 100644 --- a/hathor/p2p/sync_v2/blockchain_streaming_client.py +++ b/hathor/p2p/sync_v2/blockchain_streaming_client.py @@ -126,7 +126,7 @@ def handle_blocks(self, blk: Block) -> None: if self.tx_storage.can_validate_full(blk): try: - self.vertex_handler.on_new_vertex(blk, fails_silently=False) + self.vertex_handler.on_new_block(blk, deps=[]) except HathorError: self.fails(InvalidVertexError(blk.hash.hex())) return diff --git a/hathor/p2p/sync_v2/mempool.py b/hathor/p2p/sync_v2/mempool.py index 03651642eb..02aa3f4585 100644 --- a/hathor/p2p/sync_v2/mempool.py +++ b/hathor/p2p/sync_v2/mempool.py @@ -19,7 +19,7 @@ from twisted.internet.defer import Deferred, inlineCallbacks from hathor.exception import InvalidNewTransaction -from hathor.transaction import BaseTransaction +from hathor.transaction import Transaction if TYPE_CHECKING: from hathor.p2p.sync_v2.agent import NodeBlockSync @@ -95,7 +95,7 @@ def _unsafe_run(self) -> Generator[Deferred, Any, bool]: while self.missing_tips: self.log.debug('We have missing tips! Let\'s start!', missing_tips=[x.hex() for x in self.missing_tips]) tx_id = next(iter(self.missing_tips)) - tx: BaseTransaction = yield self.sync_agent.get_tx(tx_id) + tx: Transaction = yield self.sync_agent.get_tx(tx_id) # Stack used by the DFS in the dependencies. # We use a deque for performance reasons. self.log.debug('start mempool DSF', tx=tx.hash_hex) @@ -106,7 +106,7 @@ def _unsafe_run(self) -> Generator[Deferred, Any, bool]: return False @inlineCallbacks - def _dfs(self, stack: deque[BaseTransaction]) -> Generator[Deferred, Any, None]: + def _dfs(self, stack: deque[Transaction]) -> Generator[Deferred, Any, None]: """DFS method.""" while stack: tx = stack[-1] @@ -123,7 +123,7 @@ def _dfs(self, stack: deque[BaseTransaction]) -> Generator[Deferred, Any, None]: if len(stack) > self.MAX_STACK_LENGTH: stack.popleft() - def _next_missing_dep(self, tx: BaseTransaction) -> Optional[bytes]: + def _next_missing_dep(self, tx: Transaction) -> Optional[bytes]: """Get the first missing dependency found of tx.""" assert not tx.is_block for txin in tx.inputs: @@ -134,13 +134,13 @@ def _next_missing_dep(self, tx: BaseTransaction) -> Optional[bytes]: return parent return None - def _add_tx(self, tx: BaseTransaction) -> None: + def _add_tx(self, tx: Transaction) -> None: """Add tx to the DAG.""" self.missing_tips.discard(tx.hash) if self.tx_storage.transaction_exists(tx.hash): return try: - success = self.vertex_handler.on_new_vertex(tx, fails_silently=False) + success = self.vertex_handler.on_new_mempool_transaction(tx) if success: self.sync_agent.protocol.connections.send_tx_to_peers(tx) except InvalidNewTransaction: diff --git a/hathor/p2p/sync_v2/transaction_streaming_client.py b/hathor/p2p/sync_v2/transaction_streaming_client.py index e784a41cc2..fd7cea8795 100644 --- a/hathor/p2p/sync_v2/transaction_streaming_client.py +++ b/hathor/p2p/sync_v2/transaction_streaming_client.py @@ -25,7 +25,7 @@ UnexpectedVertex, ) from hathor.p2p.sync_v2.streamers import StreamEnd -from hathor.transaction import BaseTransaction +from hathor.transaction import BaseTransaction, Transaction from hathor.transaction.exceptions import HathorError, TxValidationError from hathor.types import VertexId @@ -66,7 +66,7 @@ def __init__(self, self._tx_max_quantity = limit # Queue of transactions waiting to be processed. - self._queue: deque[BaseTransaction] = deque() + self._queue: deque[Transaction] = deque() # Keeps the response code if the streaming has ended. self._response_code: Optional[StreamEnd] = None @@ -79,7 +79,7 @@ def __init__(self, # In-memory database of transactions already received but still # waiting for dependencies. - self._db: dict[VertexId, BaseTransaction] = {} + self._db: dict[VertexId, Transaction] = {} self._existing_deps: set[VertexId] = set() self._prepare_block(self.partial_blocks[0]) @@ -103,7 +103,7 @@ def fails(self, reason: 'StreamingError') -> None: return self._deferred.errback(reason) - def handle_transaction(self, tx: BaseTransaction) -> None: + def handle_transaction(self, tx: Transaction) -> None: """This method is called by the sync agent when a TRANSACTION message is received.""" if self._deferred.called: return @@ -147,7 +147,7 @@ def process_queue(self) -> Generator[Any, Any, None]: self.reactor.callLater(0, self.process_queue) @inlineCallbacks - def _process_transaction(self, tx: BaseTransaction) -> Generator[Any, Any, None]: + def _process_transaction(self, tx: Transaction) -> Generator[Any, Any, None]: """Process transaction.""" # Run basic verification. @@ -177,6 +177,7 @@ def _process_transaction(self, tx: BaseTransaction) -> Generator[Any, Any, None] self._update_dependencies(tx) + assert isinstance(tx, Transaction) self._db[tx.hash] = tx if not self._waiting_for: @@ -191,9 +192,9 @@ def _process_transaction(self, tx: BaseTransaction) -> Generator[Any, Any, None] if self._tx_received % 100 == 0: self.log.debug('tx streaming in progress', txs_received=self._tx_received) - def _update_dependencies(self, tx: BaseTransaction) -> None: + def _update_dependencies(self, vertex: BaseTransaction) -> None: """Update _existing_deps and _waiting_for with the dependencies.""" - for dep in tx.get_all_dependencies(): + for dep in vertex.get_all_dependencies(): if self.tx_storage.transaction_exists(dep) or dep in self._db: self._existing_deps.add(dep) else: diff --git a/hathor/simulator/miner/geometric_miner.py b/hathor/simulator/miner/geometric_miner.py index a7828e0152..f96d3fb840 100644 --- a/hathor/simulator/miner/geometric_miner.py +++ b/hathor/simulator/miner/geometric_miner.py @@ -91,7 +91,7 @@ def _schedule_next_block(self): self._block.nonce = self._rng.getrandbits(32) self._block.update_hash() self.log.debug('randomized step: found new block', hash=self._block.hash_hex, nonce=self._block.nonce) - self._manager.propagate_tx(self._block, fails_silently=False) + self._manager.propagate_tx(self._block) self._blocks_found += 1 self._blocks_before_pause -= 1 self._block = None diff --git a/hathor/simulator/tx_generator.py b/hathor/simulator/tx_generator.py index ead648da5f..ce6ff1037c 100644 --- a/hathor/simulator/tx_generator.py +++ b/hathor/simulator/tx_generator.py @@ -94,7 +94,7 @@ def schedule_next_transaction(self): """ Schedule the generation of a new transaction. """ if self.tx: - ret = self.manager.propagate_tx(self.tx, fails_silently=False) + ret = self.manager.propagate_tx(self.tx) assert ret is True self.transactions_found += 1 self.latest_transactions.appendleft(self.tx.hash) diff --git a/hathor/simulator/utils.py b/hathor/simulator/utils.py index 792380ae24..61562da50b 100644 --- a/hathor/simulator/utils.py +++ b/hathor/simulator/utils.py @@ -109,7 +109,7 @@ def add_new_block( block.signal_bits = signal_bits manager.cpu_mining_service.resolve(block) if propagate: - manager.propagate_tx(block, fails_silently=False) + manager.propagate_tx(block) if advance_clock: assert hasattr(manager.reactor, 'advance') manager.reactor.advance(advance_clock) diff --git a/hathor/stratum/stratum.py b/hathor/stratum/stratum.py index a03f052719..01bbf94bf8 100644 --- a/hathor/stratum/stratum.py +++ b/hathor/stratum/stratum.py @@ -560,7 +560,7 @@ def handle_submit(self, params: dict, msgid: Optional[str]) -> None: # We only propagate blocks here in stratum # For tx we need to propagate in the resource, # so we can get the possible errors - self.manager.submit_block(tx, fails_silently=False) + self.manager.submit_block(tx) self.blocks_found += 1 except (InvalidNewTransaction, TxValidationError) as e: # Block propagation failed, but the share was succesfully submited diff --git a/hathor/vertex_handler/vertex_handler.py b/hathor/vertex_handler/vertex_handler.py index de294c7b0e..f7ac4470d5 100644 --- a/hathor/vertex_handler/vertex_handler.py +++ b/hathor/vertex_handler/vertex_handler.py @@ -13,8 +13,11 @@ # limitations under the License. import datetime +from typing import Any, Generator from structlog import get_logger +from twisted.internet.defer import inlineCallbacks +from twisted.internet.task import deferLater from hathor.conf.settings import HathorSettings from hathor.consensus import ConsensusAlgorithm @@ -24,7 +27,7 @@ from hathor.profiler import get_cpu_profiler from hathor.pubsub import HathorEvents, PubSubManager from hathor.reactor import ReactorProtocol -from hathor.transaction import BaseTransaction, Block +from hathor.transaction import BaseTransaction, Block, Transaction from hathor.transaction.storage import TransactionStorage from hathor.transaction.storage.exceptions import TransactionDoesNotExist from hathor.verification.verification_service import VerificationService @@ -75,24 +78,50 @@ def __init__( self._wallet = wallet self._log_vertex_bytes = log_vertex_bytes - @cpu.profiler('on_new_vertex') - def on_new_vertex( + @cpu.profiler('on_new_block') + @inlineCallbacks + def on_new_block(self, block: Block, *, deps: list[Transaction]) -> Generator[Any, Any, bool]: + for tx in deps: + if not self._tx_storage.transaction_exists(tx.hash): + if not self._old_on_new_vertex(tx): + return False + yield deferLater(self._reactor, 0, lambda: None) + + if not self._tx_storage.transaction_exists(block.hash): + if not self._old_on_new_vertex(block): + return False + + return True + + @cpu.profiler('on_new_mempool_transaction') + def on_new_mempool_transaction(self, tx: Transaction) -> bool: + return self._old_on_new_vertex(tx) + + @cpu.profiler('on_new_relayed_vertex') + def on_new_relayed_vertex( + self, + vertex: BaseTransaction, + *, + quiet: bool = False, + reject_locked_reward: bool = True + ) -> bool: + return self._old_on_new_vertex(vertex, quiet=quiet, reject_locked_reward=reject_locked_reward) + + @cpu.profiler('_old_on_new_vertex') + def _old_on_new_vertex( self, vertex: BaseTransaction, *, quiet: bool = False, - fails_silently: bool = True, reject_locked_reward: bool = True, ) -> bool: """ New method for adding transactions or blocks that steps the validation state machine. :param vertex: transaction to be added :param quiet: if True will not log when a new tx is accepted - :param fails_silently: if False will raise an exception when tx cannot be added """ is_valid = self._validate_vertex( vertex, - fails_silently=fails_silently, reject_locked_reward=reject_locked_reward ) @@ -119,7 +148,6 @@ def _validate_vertex( self, vertex: BaseTransaction, *, - fails_silently: bool, reject_locked_reward: bool, ) -> bool: assert self._tx_storage.is_only_valid_allowed() @@ -129,43 +157,27 @@ def _validate_vertex( already_exists = True if vertex.timestamp - self._reactor.seconds() > self._settings.MAX_FUTURE_TIMESTAMP_ALLOWED: - if not fails_silently: - raise InvalidNewTransaction('Ignoring transaction in the future {} (timestamp={})'.format( - vertex.hash_hex, vertex.timestamp)) - self._log.warn('on_new_tx(): Ignoring transaction in the future', tx=vertex.hash_hex, - future_timestamp=vertex.timestamp) - return False + raise InvalidNewTransaction('Ignoring transaction in the future {} (timestamp={})'.format( + vertex.hash_hex, vertex.timestamp)) vertex.storage = self._tx_storage try: metadata = vertex.get_metadata() except TransactionDoesNotExist: - if not fails_silently: - raise InvalidNewTransaction('cannot get metadata') - self._log.warn('on_new_tx(): cannot get metadata', tx=vertex.hash_hex) - return False + raise InvalidNewTransaction('cannot get metadata') if already_exists and metadata.validation.is_fully_connected(): - if not fails_silently: - raise InvalidNewTransaction('Transaction already exists {}'.format(vertex.hash_hex)) - self._log.warn('on_new_tx(): Transaction already exists', tx=vertex.hash_hex) - return False + raise InvalidNewTransaction('Transaction already exists {}'.format(vertex.hash_hex)) if metadata.validation.is_invalid(): - if not fails_silently: - raise InvalidNewTransaction('previously marked as invalid') - self._log.warn('on_new_tx(): previously marked as invalid', tx=vertex.hash_hex) - return False + raise InvalidNewTransaction('previously marked as invalid') if not metadata.validation.is_fully_connected(): try: self._verification_service.validate_full(vertex, reject_locked_reward=reject_locked_reward) except HathorError as e: - if not fails_silently: - raise InvalidNewTransaction(f'full validation failed: {str(e)}') from e - self._log.warn('on_new_tx(): full validation failed', tx=vertex.hash_hex, exc_info=True) - return False + raise InvalidNewTransaction(f'full validation failed: {str(e)}') from e return True diff --git a/hathor/wallet/resources/send_tokens.py b/hathor/wallet/resources/send_tokens.py index 2d3cc74924..7e1f7ada80 100644 --- a/hathor/wallet/resources/send_tokens.py +++ b/hathor/wallet/resources/send_tokens.py @@ -140,7 +140,7 @@ def _cb_tx_resolve(self, tx, request): """ message = '' try: - success = self.manager.propagate_tx(tx, fails_silently=False) + success = self.manager.propagate_tx(tx) except (InvalidNewTransaction, TxValidationError) as e: success = False message = str(e) diff --git a/hathor/wallet/resources/thin_wallet/send_tokens.py b/hathor/wallet/resources/thin_wallet/send_tokens.py index 0ab18f5b90..cc86e8f756 100644 --- a/hathor/wallet/resources/thin_wallet/send_tokens.py +++ b/hathor/wallet/resources/thin_wallet/send_tokens.py @@ -282,7 +282,7 @@ def _cb_tx_resolve(self, context: _Context) -> None: message = '' return_code = '' try: - success = self.manager.propagate_tx(tx, fails_silently=False) + success = self.manager.propagate_tx(tx) if success: return_code = 'success' else: diff --git a/tests/cli/test_multisig_spend.py b/tests/cli/test_multisig_spend.py index 7b427ed784..ebbf61dd2d 100644 --- a/tests/cli/test_multisig_spend.py +++ b/tests/cli/test_multisig_spend.py @@ -118,4 +118,4 @@ def test_spend_multisig(self): tx_raw = output[0].split(':')[1].strip() tx = Transaction.create_from_struct(bytes.fromhex(tx_raw)) - self.assertTrue(self.manager.propagate_tx(tx, False)) + self.assertTrue(self.manager.propagate_tx(tx)) diff --git a/tests/consensus/test_consensus.py b/tests/consensus/test_consensus.py index fcda1bdd2b..0da029cdb8 100644 --- a/tests/consensus/test_consensus.py +++ b/tests/consensus/test_consensus.py @@ -33,7 +33,7 @@ class MyError(Exception): manager.vertex_handler._execution_manager = execution_manager_mock manager.consensus_algorithm.unsafe_update = MagicMock(side_effect=MyError) - manager.propagate_tx(tx, fails_silently=False) + manager.propagate_tx(tx) execution_manager_mock.crash_and_exit.assert_called_once_with( reason=f"on_new_vertex() failed for tx {tx.hash_hex}" @@ -78,7 +78,7 @@ def test_revert_block_high_weight(self) -> None: b0 = tb0.generate_mining_block(manager.rng, storage=manager.tx_storage) b0.weight = 10 manager.cpu_mining_service.resolve(b0) - manager.propagate_tx(b0, fails_silently=False) + manager.propagate_tx(b0) b1 = add_new_block(manager, advance_clock=15) b2 = add_new_block(manager, advance_clock=15) @@ -139,7 +139,7 @@ def test_dont_revert_block_low_weight(self) -> None: b0 = manager.generate_mining_block() b0.parents = [blocks[-1].hash, conflicting_tx.hash, conflicting_tx.parents[0]] manager.cpu_mining_service.resolve(b0) - manager.propagate_tx(b0, fails_silently=False) + manager.propagate_tx(b0) b1 = add_new_block(manager, advance_clock=15) b2 = add_new_block(manager, advance_clock=15) @@ -194,7 +194,7 @@ def test_dont_revert_block_high_weight_transaction_verify_other(self) -> None: b0 = tb0.generate_mining_block(manager.rng, storage=manager.tx_storage) b0.weight = 10 manager.cpu_mining_service.resolve(b0) - manager.propagate_tx(b0, fails_silently=False) + manager.propagate_tx(b0) b1 = add_new_block(manager, advance_clock=15) b2 = add_new_block(manager, advance_clock=15) @@ -247,7 +247,7 @@ def test_dont_revert_block_high_weight_verify_both(self) -> None: b0.parents = [b0.parents[0], conflicting_tx.hash, conflicting_tx.parents[0]] b0.weight = 10 manager.cpu_mining_service.resolve(b0) - manager.propagate_tx(b0, fails_silently=False) + manager.propagate_tx(b0) b1 = add_new_block(manager, advance_clock=15) b2 = add_new_block(manager, advance_clock=15) diff --git a/tests/consensus/test_consensus2.py b/tests/consensus/test_consensus2.py index 82fa9be601..c4318b7767 100644 --- a/tests/consensus/test_consensus2.py +++ b/tests/consensus/test_consensus2.py @@ -80,7 +80,7 @@ def test_two_conflicts_intertwined_once(self) -> None: initial = gen_new_tx(manager1, address, value) initial.weight = 25 initial.update_hash() - manager1.propagate_tx(initial, fails_silently=False) + manager1.propagate_tx(initial) self.graphviz.labels[initial.hash] = 'initial' x = initial @@ -116,7 +116,7 @@ def test_two_conflicts_intertwined_multiple_times(self) -> None: initial = gen_new_tx(manager1, address, value) initial.weight = 25 initial.update_hash() - manager1.propagate_tx(initial, fails_silently=False) + manager1.propagate_tx(initial) self.graphviz.labels[not_none(initial.hash)] = 'initial' x = initial diff --git a/tests/consensus/test_consensus5.py b/tests/consensus/test_consensus5.py index fa40dfd295..d119c6f59f 100644 --- a/tests/consensus/test_consensus5.py +++ b/tests/consensus/test_consensus5.py @@ -62,7 +62,7 @@ def test_conflict_with_parent_tx(self) -> None: b2.nonce = self.rng.getrandbits(32) b2.update_hash() self.graphviz.labels[b2.hash] = 'b2' - self.assertTrue(manager1.propagate_tx(b2, fails_silently=False)) + self.assertTrue(manager1.propagate_tx(b2)) self.simulator.run(10) self.assertIsNone(txA1.get_metadata().voided_by) diff --git a/tests/consensus/test_soft_voided.py b/tests/consensus/test_soft_voided.py index a1bc57a190..74b3650e9b 100644 --- a/tests/consensus/test_soft_voided.py +++ b/tests/consensus/test_soft_voided.py @@ -89,7 +89,7 @@ def _run_test( txC.timestamp = max(txC.timestamp, txA.timestamp + 1) txC.weight = 25 txC.update_hash() - self.assertTrue(manager2.propagate_tx(txC, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(txC)) metaC = txC.get_metadata() self.assertIsNone(metaC.voided_by) graphviz.labels[txC.hash] = 'txC' @@ -99,7 +99,7 @@ def _run_test( blk1.parents[1] = txA.hash blk1.nonce = self.rng.getrandbits(32) blk1.update_hash() - self.assertTrue(manager2.propagate_tx(blk1, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk1)) blk1meta = blk1.get_metadata() self.assertIsNone(blk1meta.voided_by) graphviz.labels[blk1.hash] = 'b1' @@ -110,7 +110,7 @@ def _run_test( blk2.parents[1] = txD1.hash blk2.nonce = self.rng.getrandbits(32) blk2.update_hash() - self.assertTrue(manager2.propagate_tx(blk2, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk2)) blk2meta = blk2.get_metadata() self.assertIsNone(blk2meta.voided_by) graphviz.labels[blk2.hash] = 'b2' @@ -120,7 +120,7 @@ def _run_test( blk3.parents[1] = txD2.hash blk3.nonce = self.rng.getrandbits(32) blk3.update_hash() - self.assertTrue(manager2.propagate_tx(blk3, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk3)) blk3meta = blk3.get_metadata() self.assertIsNone(blk3meta.voided_by) graphviz.labels[blk3.hash] = 'b3' diff --git a/tests/consensus/test_soft_voided2.py b/tests/consensus/test_soft_voided2.py index 70881c6276..852af9c617 100644 --- a/tests/consensus/test_soft_voided2.py +++ b/tests/consensus/test_soft_voided2.py @@ -99,7 +99,7 @@ def gen_block(self, manager1: HathorManager, tx: Transaction, parent_block: Bloc block.timestamp = max(block.timestamp, tx.timestamp + 1) block.nonce = self.rng.getrandbits(32) block.update_hash() - self.assertTrue(manager1.propagate_tx(block, fails_silently=False)) + self.assertTrue(manager1.propagate_tx(block)) return block def _run_test(self, simulator: Simulator, soft_voided_tx_ids: set[VertexId]) -> Iterator[None]: @@ -124,7 +124,7 @@ def _run_test(self, simulator: Simulator, soft_voided_tx_ids: set[VertexId]) -> initial = gen_new_tx(manager1, address, value) initial.weight = 25 initial.update_hash() - manager1.propagate_tx(initial, fails_silently=False) + manager1.propagate_tx(initial) self.graphviz.labels[initial.hash] = 'initial' x = initial diff --git a/tests/consensus/test_soft_voided3.py b/tests/consensus/test_soft_voided3.py index bdb8c0a7c0..38f803ebd9 100644 --- a/tests/consensus/test_soft_voided3.py +++ b/tests/consensus/test_soft_voided3.py @@ -84,7 +84,7 @@ def _run_test( blk1.timestamp = txD1.timestamp + 1 blk1.nonce = self.rng.getrandbits(32) blk1.update_hash() - self.assertTrue(manager2.propagate_tx(blk1, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk1)) blk1meta = blk1.get_metadata() self.assertIsNone(blk1meta.voided_by) graphviz.labels[blk1.hash] = 'blk1' @@ -97,7 +97,7 @@ def _run_test( txC.parents[1] = txD1.hash txC.weight = 25 txC.update_hash() - manager2.propagate_tx(txC, fails_silently=False) + manager2.propagate_tx(txC) metaC = txC.get_metadata() self.assertIsNone(metaC.voided_by) graphviz.labels[txC.hash] = 'txC' @@ -105,7 +105,7 @@ def _run_test( txD2 = gen_custom_tx(manager2, [(txB, 0)]) txD2.timestamp = txD1.timestamp + 2 txD2.update_hash() - manager2.propagate_tx(txD2, fails_silently=False) + manager2.propagate_tx(txD2) graphviz.labels[txD2.hash] = 'txD2' blk1meta = blk1.get_metadata() diff --git a/tests/consensus/test_soft_voided4.py b/tests/consensus/test_soft_voided4.py index f60dab477d..7bb510f750 100644 --- a/tests/consensus/test_soft_voided4.py +++ b/tests/consensus/test_soft_voided4.py @@ -79,7 +79,7 @@ def _run_test( txC.parents = tx_base.parents txC.update_hash() self.graphviz.labels[txC.hash] = 'txC' - self.assertTrue(manager2.propagate_tx(txC, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(txC)) metaC = txC.get_metadata() self.assertIsNone(metaC.voided_by) @@ -99,7 +99,7 @@ def _run_test( # dot = self.graphviz.dot() # dot.render('dot0') - self.assertTrue(manager2.propagate_tx(blk1, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk1)) blk1meta = blk1.get_metadata() self.graphviz.labels[blk1.hash] = 'blk1' self.assertIsNone(blk1meta.voided_by) @@ -110,7 +110,7 @@ def _run_test( blk2.update_timestamp(int(manager2.reactor.seconds())) blk2.nonce = self.rng.getrandbits(32) blk2.update_hash() - self.assertTrue(manager2.propagate_tx(blk2, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk2)) blk2meta = blk2.get_metadata() self.graphviz.labels[blk2.hash] = 'blk2' self.assertIsNone(blk2meta.voided_by) @@ -121,7 +121,7 @@ def _run_test( blk3.parents[1] = txB.hash blk3.nonce = self.rng.getrandbits(32) blk3.update_hash() - self.assertTrue(manager2.propagate_tx(blk3, fails_silently=False)) + self.assertTrue(manager2.propagate_tx(blk3)) blk3meta = blk3.get_metadata() self.graphviz.labels[blk3.hash] = 'blk3' diff --git a/tests/event/test_event_reorg.py b/tests/event/test_event_reorg.py index b105b3bc99..e55d7909c8 100644 --- a/tests/event/test_event_reorg.py +++ b/tests/event/test_event_reorg.py @@ -35,7 +35,7 @@ def test_reorg_events(self) -> None: b0 = tb0.generate_mining_block(self.manager.rng, storage=self.manager.tx_storage, address=BURN_ADDRESS) b0.weight = 10 self.manager.cpu_mining_service.resolve(b0) - self.manager.propagate_tx(b0, fails_silently=False) + self.manager.propagate_tx(b0) self.log.debug('reorg block propagated') self.run_to_completion() diff --git a/tests/feature_activation/test_feature_simulation.py b/tests/feature_activation/test_feature_simulation.py index 95f26aa31e..c6021791b8 100644 --- a/tests/feature_activation/test_feature_simulation.py +++ b/tests/feature_activation/test_feature_simulation.py @@ -19,6 +19,7 @@ from hathor.builder import Builder from hathor.conf.get_settings import get_global_settings +from hathor.exception import InvalidNewTransaction from hathor.feature_activation.feature import Feature from hathor.feature_activation.feature_service import FeatureService from hathor.feature_activation.model.criteria import Criteria @@ -108,7 +109,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*10) tx.weight = 25 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=10, @@ -146,7 +147,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*19) tx.weight = 25 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=19, @@ -183,7 +184,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*20) tx.weight = 25 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=20, @@ -222,7 +223,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*55) tx.weight = 30 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=55, @@ -258,7 +259,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*56) tx.weight = 30 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=56, @@ -300,7 +301,8 @@ def test_feature(self) -> None: with pytest.raises(BlockMustSignalError): manager.verification_service.verify(non_signaling_block) - assert not manager.propagate_tx(non_signaling_block) + with pytest.raises(InvalidNewTransaction): + manager.propagate_tx(non_signaling_block) # at block 59, the feature is MUST_SIGNAL, just before becoming LOCKED_IN: [*_, last_block] = add_new_blocks(manager, num_blocks=2, signal_bits=0b1) @@ -308,7 +310,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*59) tx.weight = 30 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=59, @@ -345,7 +347,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*60) tx.weight = 30 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=60, @@ -384,7 +386,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*71) tx.weight = 30 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=71, @@ -420,7 +422,7 @@ def test_feature(self) -> None: tx = gen_new_tx(manager, address, 6400*72) tx.weight = 30 tx.update_hash() - assert manager.propagate_tx(tx, fails_silently=False) + assert manager.propagate_tx(tx) result = self._get_result(web_client) assert result == dict( block_height=72, diff --git a/tests/p2p/test_double_spending.py b/tests/p2p/test_double_spending.py index 1cfedead8d..abfa4e2025 100644 --- a/tests/p2p/test_double_spending.py +++ b/tests/p2p/test_double_spending.py @@ -63,14 +63,14 @@ def test_simple_double_spending(self) -> None: self.assertNotEqual(tx1.hash, tx3.hash) self.assertNotEqual(tx2.hash, tx3.hash) - self.assertTrue(self.manager1.propagate_tx(tx1, False)) + self.assertTrue(self.manager1.propagate_tx(tx1)) self.run_to_completion() meta1 = tx1.get_metadata() self.assertEqual(meta1.conflict_with, None) self.assertEqual(meta1.voided_by, None) # Propagate a conflicting transaction. - self.assertTrue(self.manager1.propagate_tx(tx2, False)) + self.assertTrue(self.manager1.propagate_tx(tx2)) self.run_to_completion() meta1 = tx1.get_metadata(force_reload=True) @@ -225,7 +225,7 @@ def test_double_spending_propagation(self) -> None: # --- self.clock.advance(15) - self.assertTrue(self.manager1.propagate_tx(tx4, False)) + self.assertTrue(self.manager1.propagate_tx(tx4)) self.clock.advance(15) self.run_to_completion() @@ -287,7 +287,7 @@ def test_double_spending_propagation(self) -> None: tx7.timestamp = int(self.clock.seconds()) self.manager1.cpu_mining_service.resolve(tx7) self.clock.advance(15) - self.manager1.propagate_tx(tx7, False) + self.manager1.propagate_tx(tx7) self.clock.advance(15) meta1 = tx1.get_metadata(force_reload=True) diff --git a/tests/poa/test_poa_simulation.py b/tests/poa/test_poa_simulation.py index 384f7d1d49..73776f32a1 100644 --- a/tests/poa/test_poa_simulation.py +++ b/tests/poa/test_poa_simulation.py @@ -565,4 +565,4 @@ def test_use_case(self) -> None: token_tx.inputs[0].data = P2PKH.create_input_data(public_key_bytes, signature) token_tx.update_hash() - assert manager.on_new_tx(token_tx, fails_silently=False) + assert manager.on_new_tx(token_tx) diff --git a/tests/tx/test_indexes.py b/tests/tx/test_indexes.py index 0d13ea63ad..215016b374 100644 --- a/tests/tx/test_indexes.py +++ b/tests/tx/test_indexes.py @@ -29,7 +29,7 @@ def test_tx_tips_with_conflict(self): tx1.parents = self.manager.get_new_tx_parents() tx1.timestamp = int(self.clock.seconds()) self.manager.cpu_mining_service.resolve(tx1) - self.assertTrue(self.manager.propagate_tx(tx1, False)) + self.assertTrue(self.manager.propagate_tx(tx1)) if self.manager.tx_storage.indexes.mempool_tips is not None: self.assertEqual( {tx.hash for tx in self.manager.tx_storage.indexes.mempool_tips.iter(self.manager.tx_storage)}, @@ -44,7 +44,7 @@ def test_tx_tips_with_conflict(self): self.assertIn(tx1.hash, tx2.parents) tx2.timestamp = int(self.clock.seconds()) + 1 self.manager.cpu_mining_service.resolve(tx2) - self.assertTrue(self.manager.propagate_tx(tx2, False)) + self.assertTrue(self.manager.propagate_tx(tx2)) if self.manager.tx_storage.indexes.mempool_tips is not None: self.assertEqual( {tx.hash for tx in self.manager.tx_storage.indexes.mempool_tips.iter(self.manager.tx_storage)}, @@ -56,7 +56,7 @@ def test_tx_tips_with_conflict(self): self.assertIn(tx1.hash, tx3.parents) self.manager.cpu_mining_service.resolve(tx3) self.assertNotEqual(tx2.hash, tx3.hash) - self.assertTrue(self.manager.propagate_tx(tx3, False)) + self.assertTrue(self.manager.propagate_tx(tx3)) self.assertIn(tx3.hash, tx2.get_metadata().conflict_with) if self.manager.tx_storage.indexes.mempool_tips is not None: self.assertEqual( @@ -86,7 +86,7 @@ def test_tx_tips_voided(self): tx1.parents = self.manager.get_new_tx_parents() tx1.timestamp = int(self.clock.seconds()) self.manager.cpu_mining_service.resolve(tx1) - self.assertTrue(self.manager.propagate_tx(tx1, False)) + self.assertTrue(self.manager.propagate_tx(tx1)) if self.manager.tx_storage.indexes.mempool_tips is not None: self.assertEqual( {tx.hash for tx in self.manager.tx_storage.indexes.mempool_tips.iter(self.manager.tx_storage)}, @@ -99,7 +99,7 @@ def test_tx_tips_voided(self): self.assertIn(tx1.hash, tx2.parents) tx2.timestamp = int(self.clock.seconds()) + 1 self.manager.cpu_mining_service.resolve(tx2) - self.assertTrue(self.manager.propagate_tx(tx2, False)) + self.assertTrue(self.manager.propagate_tx(tx2)) if self.manager.tx_storage.indexes.mempool_tips is not None: self.assertEqual( {tx.hash for tx in self.manager.tx_storage.indexes.mempool_tips.iter(self.manager.tx_storage)}, @@ -113,7 +113,7 @@ def test_tx_tips_voided(self): # self.assertIn(tx1.hash, tx3.parents) self.manager.cpu_mining_service.resolve(tx3) self.assertNotEqual(tx2.hash, tx3.hash) - self.assertTrue(self.manager.propagate_tx(tx3, False)) + self.assertTrue(self.manager.propagate_tx(tx3)) # self.assertIn(tx3.hash, tx2.get_metadata().voided_by) self.assertIn(tx3.hash, tx2.get_metadata().conflict_with) if self.manager.tx_storage.indexes.mempool_tips is not None: @@ -264,7 +264,7 @@ def check_utxos(*args): block2.timestamp = block1.timestamp block2.weight = 4 self.manager.cpu_mining_service.resolve(block2) - self.manager.propagate_tx(block2, fails_silently=False) + self.manager.propagate_tx(block2) self.graphviz.labels[block2.hash] = 'block2' # make sure a reorg did happen as expected @@ -483,7 +483,7 @@ def test_utxo_index_after_push_tx(self): *wallet.get_input_aux_data(tx1.get_sighash_all(), wallet.get_private_key(address)) ) self.manager.cpu_mining_service.resolve(tx1) - self.assertTrue(self.manager.propagate_tx(tx1, False)) + self.assertTrue(self.manager.propagate_tx(tx1)) self.assertEqual( list(utxo_index.iter_utxos(address=address, target_amount=1)), @@ -558,7 +558,7 @@ def test_utxo_index_last(self): *wallet.get_input_aux_data(tx1.get_sighash_all(), wallet.get_private_key(address)) ) self.manager.cpu_mining_service.resolve(tx1) - self.assertTrue(self.manager.propagate_tx(tx1, False)) + self.assertTrue(self.manager.propagate_tx(tx1)) # querying for exact values diff --git a/tests/tx/test_indexes4.py b/tests/tx/test_indexes4.py index 54664fa41a..8416cc21eb 100644 --- a/tests/tx/test_indexes4.py +++ b/tests/tx/test_indexes4.py @@ -28,7 +28,7 @@ def _build_randomized_blockchain(self, *, utxo_index=False): tx1.parents = manager.get_new_tx_parents() tx1.timestamp = int(self.clock.seconds()) manager.cpu_mining_service.resolve(tx1) - assert manager.propagate_tx(tx1, False) + assert manager.propagate_tx(tx1) tx2 = manager.wallet.prepare_transaction_compute_inputs(Transaction, outputs, manager.tx_storage) tx2.weight = 2.0 @@ -36,13 +36,13 @@ def _build_randomized_blockchain(self, *, utxo_index=False): self.assertIn(tx1.hash, tx2.parents) tx2.timestamp = int(self.clock.seconds()) + 1 manager.cpu_mining_service.resolve(tx2) - assert manager.propagate_tx(tx2, False) + assert manager.propagate_tx(tx2) tx3 = Transaction.create_from_struct(tx2.get_struct()) tx3.weight = 3.0 tx3.parents = tx1.parents manager.cpu_mining_service.resolve(tx3) - assert manager.propagate_tx(tx3, False) + assert manager.propagate_tx(tx3) for _ in range(100): address = self.get_address(0) diff --git a/tests/tx/test_multisig.py b/tests/tx/test_multisig.py index 25222b90d9..82ac152d92 100644 --- a/tests/tx/test_multisig.py +++ b/tests/tx/test_multisig.py @@ -1,6 +1,7 @@ import base58 from hathor.crypto.util import decode_address, get_private_key_from_bytes, get_public_key_bytes_compressed +from hathor.exception import InvalidNewTransaction from hathor.simulator.utils import add_new_blocks from hathor.transaction import Transaction, TxInput, TxOutput from hathor.transaction.exceptions import ScriptError @@ -102,7 +103,8 @@ def test_spend_multisig(self): self.manager.cpu_mining_service.resolve(tx) # Transaction is still locked - self.assertFalse(self.manager.propagate_tx(tx)) + with self.assertRaises(InvalidNewTransaction): + self.manager.propagate_tx(tx) self.clock.advance(6) tx.timestamp = int(self.clock.seconds()) @@ -116,7 +118,8 @@ def test_spend_multisig(self): tx2 = Transaction.create_from_struct(tx.get_struct()) tx2.inputs[0].data = p2pkh_input_data self.manager.cpu_mining_service.resolve(tx2) - self.assertFalse(self.manager.propagate_tx(tx2)) + with self.assertRaises(InvalidNewTransaction): + self.manager.propagate_tx(tx2) # Now we propagate the correct self.assertTrue(self.manager.propagate_tx(tx)) diff --git a/tests/tx/test_reward_lock.py b/tests/tx/test_reward_lock.py index 31d4f6e69a..59af74e4e1 100644 --- a/tests/tx/test_reward_lock.py +++ b/tests/tx/test_reward_lock.py @@ -78,7 +78,7 @@ def test_classic_reward_lock(self) -> None: # now it should be spendable tx, _ = self._spend_reward_tx(self.manager, reward_block) self.assertEqual(tx.static_metadata.min_height, unlock_height) - self.assertTrue(self.manager.propagate_tx(tx, fails_silently=False)) + self.assertTrue(self.manager.propagate_tx(tx)) def test_block_with_not_enough_height(self) -> None: # add block with a reward we can spend @@ -92,7 +92,7 @@ def test_block_with_not_enough_height(self) -> None: # transaction before it can the RewardLocked exception is raised tx, _ = self._spend_reward_tx(self.manager, reward_block) self.assertEqual(tx.static_metadata.min_height, unlock_height) - self.assertTrue(self.manager.on_new_tx(tx, fails_silently=False, reject_locked_reward=False)) + self.assertTrue(self.manager.on_new_tx(tx, reject_locked_reward=False)) # new block will try to confirm it and fail with pytest.raises(InvalidNewTransaction) as e: @@ -114,7 +114,7 @@ def test_block_with_enough_height(self) -> None: # add tx that spends the reward tx, _ = self._spend_reward_tx(self.manager, reward_block) self.assertEqual(tx.static_metadata.min_height, unlock_height) - self.assertTrue(self.manager.on_new_tx(tx, fails_silently=False)) + self.assertTrue(self.manager.on_new_tx(tx)) # new block will be able to confirm it add_new_blocks(self.manager, 1, advance_clock=1) @@ -134,7 +134,7 @@ def test_mempool_tx_with_not_enough_height(self) -> None: with self.assertRaises(RewardLocked): self.manager.verification_service.verify(tx) with self.assertRaises(InvalidNewTransaction): - self.assertTrue(self.manager.on_new_tx(tx, fails_silently=False)) + self.assertTrue(self.manager.on_new_tx(tx)) def test_mempool_tx_with_enough_height(self) -> None: # add block with a reward we can spend @@ -146,7 +146,7 @@ def test_mempool_tx_with_enough_height(self) -> None: # add tx that spends the reward, must not fail tx, _ = self._spend_reward_tx(self.manager, reward_block) self.assertEqual(tx.static_metadata.min_height, unlock_height) - self.assertTrue(self.manager.on_new_tx(tx, fails_silently=False)) + self.assertTrue(self.manager.on_new_tx(tx)) def test_mempool_tx_invalid_after_reorg(self) -> None: # add block with a reward we can spend @@ -160,7 +160,7 @@ def test_mempool_tx_invalid_after_reorg(self) -> None: balance_per_address = self.manager.wallet.get_balance_per_address(self._settings.HATHOR_TOKEN_UID) assert tx_address not in balance_per_address self.assertEqual(tx.static_metadata.min_height, unlock_height) - self.assertTrue(self.manager.on_new_tx(tx, fails_silently=False)) + self.assertTrue(self.manager.on_new_tx(tx)) balance_per_address = self.manager.wallet.get_balance_per_address(self._settings.HATHOR_TOKEN_UID) assert balance_per_address[tx_address] == 6400 @@ -170,7 +170,7 @@ def test_mempool_tx_invalid_after_reorg(self) -> None: b0 = tb0.generate_mining_block(self.manager.rng, storage=self.manager.tx_storage) b0.weight = 10 self.manager.cpu_mining_service.resolve(b0) - self.manager.propagate_tx(b0, fails_silently=False) + self.manager.propagate_tx(b0) self.clock.advance(1) # now the new tx should not pass verification considering the reward lock diff --git a/tests/tx/test_timelock.py b/tests/tx/test_timelock.py index 638da9038f..cf829cf2a4 100644 --- a/tests/tx/test_timelock.py +++ b/tests/tx/test_timelock.py @@ -1,4 +1,5 @@ from hathor.crypto.util import decode_address +from hathor.exception import InvalidNewTransaction from hathor.simulator.utils import add_new_blocks from hathor.transaction import Transaction from hathor.wallet.base_wallet import WalletBalance, WalletInputInfo, WalletOutputInfo @@ -57,11 +58,11 @@ def test_timelock(self): tx2.parents = self.manager.get_new_tx_parents() tx2.timestamp = int(self.clock.seconds()) self.manager.cpu_mining_service.resolve(tx2) - propagated = self.manager.propagate_tx(tx2) + with self.assertRaises(InvalidNewTransaction): + self.manager.propagate_tx(tx2) self.assertEqual(self.manager.wallet.balance[self._settings.HATHOR_TOKEN_UID], WalletBalance(500, sum(blocks_tokens) - 500)) - self.assertFalse(propagated) self.clock.advance(1) @@ -77,7 +78,7 @@ def test_timelock(self): tx3.parents = self.manager.get_new_tx_parents() tx3.timestamp = int(self.clock.seconds()) self.manager.cpu_mining_service.resolve(tx3) - propagated = self.manager.propagate_tx(tx3, False) + propagated = self.manager.propagate_tx(tx3) self.assertEqual(self.manager.wallet.balance[self._settings.HATHOR_TOKEN_UID], WalletBalance(500, sum(blocks_tokens) - 500 - 700)) self.assertTrue(propagated) @@ -97,7 +98,7 @@ def test_timelock(self): tx4.parents = self.manager.get_new_tx_parents() tx4.timestamp = int(self.clock.seconds()) self.manager.cpu_mining_service.resolve(tx4) - propagated = self.manager.propagate_tx(tx4, False) + propagated = self.manager.propagate_tx(tx4) self.assertEqual(self.manager.wallet.balance[self._settings.HATHOR_TOKEN_UID], WalletBalance(500, sum(blocks_tokens[:3]))) self.assertTrue(propagated) @@ -105,7 +106,7 @@ def test_timelock(self): self.clock.advance(8) tx2.timestamp = int(self.clock.seconds()) self.manager.cpu_mining_service.resolve(tx2) - propagated = self.manager.propagate_tx(tx2, False) + propagated = self.manager.propagate_tx(tx2) self.assertEqual(self.manager.wallet.balance[self._settings.HATHOR_TOKEN_UID], WalletBalance(0, sum(blocks_tokens[:3]))) self.assertTrue(propagated) diff --git a/tests/tx/test_tips.py b/tests/tx/test_tips.py index d3f99ef703..b4520bbba0 100644 --- a/tests/tx/test_tips.py +++ b/tests/tx/test_tips.py @@ -65,7 +65,7 @@ def test_tips_winner(self): new_block = add_new_block(self.manager, propagate=False) new_block.parents = [new_block.parents[0], tx1.hash, tx3.hash] self.manager.cpu_mining_service.resolve(new_block) - self.manager.propagate_tx(new_block, fails_silently=False) + self.manager.propagate_tx(new_block) self.manager.reactor.advance(10) @@ -133,7 +133,7 @@ def test_tips_twin(self): tx4 = add_new_transactions(self.manager, 1, advance_clock=1, propagate=False)[0] tx4.parents = [tx1.hash, tx2.hash] self.manager.cpu_mining_service.resolve(tx4) - self.manager.propagate_tx(tx4, fails_silently=False) + self.manager.propagate_tx(tx4) self.manager.reactor.advance(10) self.assertCountEqual(self.get_tips(), set([tx4.hash, tx3.hash])) @@ -153,7 +153,7 @@ def test_tips_twin(self): tx6 = add_new_transactions(self.manager, 1, advance_clock=1, propagate=False)[0] tx6.parents = [tx5.hash, tx2.hash] self.manager.cpu_mining_service.resolve(tx6) - self.manager.propagate_tx(tx6, fails_silently=False) + self.manager.propagate_tx(tx6) self.manager.reactor.advance(10) self.assertIsNotNone(tx4.get_metadata(force_reload=True).voided_by) self.assertIsNone(tx5.get_metadata(force_reload=True).voided_by) diff --git a/tests/tx/test_tx.py b/tests/tx/test_tx.py index a222ce295d..5b00f8694c 100644 --- a/tests/tx/test_tx.py +++ b/tests/tx/test_tx.py @@ -684,26 +684,30 @@ def test_propagation_error(self): # 1. propagate genesis genesis_block = self.genesis_blocks[0] genesis_block.storage = manager.tx_storage - self.assertFalse(manager.propagate_tx(genesis_block)) + with self.assertRaises(InvalidNewTransaction): + manager.propagate_tx(genesis_block) # 2. propagate block with weight 1 block = manager.generate_mining_block() block.weight = 1 self.manager.cpu_mining_service.resolve(block) - self.assertFalse(manager.propagate_tx(block)) + with self.assertRaises(InvalidNewTransaction): + manager.propagate_tx(block) # 3. propagate block with wrong amount of tokens block = manager.generate_mining_block() output = TxOutput(1, block.outputs[0].script) block.outputs = [output] self.manager.cpu_mining_service.resolve(block) - self.assertFalse(manager.propagate_tx(block)) + with self.assertRaises(InvalidNewTransaction): + manager.propagate_tx(block) # 4. propagate block from the future block = manager.generate_mining_block() block.timestamp = int(self.clock.seconds()) + self._settings.MAX_FUTURE_TIMESTAMP_ALLOWED + 100 manager.cpu_mining_service.resolve(block, update_time=False) - self.assertFalse(manager.propagate_tx(block)) + with self.assertRaises(InvalidNewTransaction): + manager.propagate_tx(block) def test_tx_methods(self): blocks = add_new_blocks(self.manager, 2, advance_clock=1) diff --git a/tests/tx/test_tx_storage.py b/tests/tx/test_tx_storage.py index 105b8bfad3..d04eb890c4 100644 --- a/tests/tx/test_tx_storage.py +++ b/tests/tx/test_tx_storage.py @@ -513,7 +513,7 @@ def _add_new_block(self, parents=None): block.parents = parents block.weight = 10 self.assertTrue(self.manager.cpu_mining_service.resolve(block)) - self.manager.propagate_tx(block, fails_silently=False) + self.manager.propagate_tx(block) self.reactor.advance(5) return block diff --git a/tests/utils.py b/tests/utils.py index 54347004e4..08a2101df2 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -51,7 +51,7 @@ def add_custom_tx(manager: HathorManager, tx_inputs: list[tuple[BaseTransaction, """Add a custom tx based on the gen_custom_tx(...) method.""" tx = gen_custom_tx(manager, tx_inputs, n_outputs=n_outputs, base_parent=base_parent, weight=weight, resolve=resolve, address=address, inc_timestamp=inc_timestamp) - manager.propagate_tx(tx, fails_silently=False) + manager.propagate_tx(tx) return tx @@ -122,7 +122,7 @@ def gen_custom_tx(manager: HathorManager, tx_inputs: list[tuple[BaseTransaction, def add_new_double_spending(manager: HathorManager, *, use_same_parents: bool = False, tx: Optional[Transaction] = None, weight: float = 1) -> Transaction: tx = gen_new_double_spending(manager, use_same_parents=use_same_parents, tx=tx, weight=weight) - manager.propagate_tx(tx, fails_silently=False) + manager.propagate_tx(tx) return tx @@ -149,7 +149,7 @@ def add_new_tx( """ tx = gen_new_tx(manager, address, value) if propagate: - manager.propagate_tx(tx, fails_silently=False) + manager.propagate_tx(tx) if advance_clock: manager.reactor.advance(advance_clock) # type: ignore[attr-defined] return tx @@ -472,7 +472,7 @@ def create_tokens(manager: 'HathorManager', address_b58: Optional[str] = None, m manager.cpu_mining_service.resolve(tx) if propagate: - manager.propagate_tx(tx, fails_silently=False) + manager.propagate_tx(tx) assert isinstance(manager.reactor, Clock) manager.reactor.advance(8) return tx @@ -561,7 +561,7 @@ def add_tx_with_data_script(manager: 'HathorManager', data: list[str], propagate if propagate: manager.verification_service.verify(tx) - manager.propagate_tx(tx, fails_silently=False) + manager.propagate_tx(tx) assert isinstance(manager.reactor, Clock) manager.reactor.advance(8) diff --git a/tests/wallet/test_wallet.py b/tests/wallet/test_wallet.py index 48d1890b88..9f1c52bf3b 100644 --- a/tests/wallet/test_wallet.py +++ b/tests/wallet/test_wallet.py @@ -265,6 +265,6 @@ def test_maybe_spent_txs(self): tx2.weight = 1 tx2.timestamp = blocks[-1].timestamp + 1 self.manager.cpu_mining_service.resolve(tx2) - self.assertTrue(self.manager.on_new_tx(tx2, fails_silently=False)) + self.assertTrue(self.manager.on_new_tx(tx2)) self.clock.advance(2) self.assertEqual(0, len(w.maybe_spent_txs[self._settings.HATHOR_TOKEN_UID]))