def on_new_tx(self, tx: BaseTransaction, *, conn: Optional[HathorProtocol] = None, quiet: bool = False, fails_silently: bool = True, propagate_to_peers: bool = True) -> bool: """This method is called when any transaction arrive. If `fails_silently` is False, it may raise either InvalidNewTransaction or TxValidationError. :return: True if the transaction was accepted :rtype: bool """ assert tx.hash is not None if self.state != self.NodeState.INITIALIZING: if self.tx_storage.transaction_exists(tx.hash): if not fails_silently: raise InvalidNewTransaction( 'Transaction already exists {}'.format(tx.hash.hex())) self.log.debug( 'on_new_tx(): Already have transaction {}'.format( tx.hash.hex())) return False try: assert self.validate_new_tx(tx) is True except (InvalidNewTransaction, TxValidationError) as e: # Discard invalid Transaction/block. self.log.debug('Transaction/Block discarded', tx=tx, exc=e) if not fails_silently: raise return False if self.state != self.NodeState.INITIALIZING: self.tx_storage.save_transaction(tx) else: tx.reset_metadata() self.tx_storage._add_to_cache(tx) try: tx.update_initial_metadata() self.consensus_algorithm.update(tx) except Exception: pretty_json = json.dumps(tx.to_json(), indent=4) self.log.error( 'An unexpected error occurred when processing {tx.hash_hex}\n' '{pretty_json}', tx=tx, pretty_json=pretty_json) self.tx_storage.remove_transaction(tx) raise if not quiet: ts_date = datetime.datetime.fromtimestamp(tx.timestamp) if tx.is_block: self.log.info('New block found', tag='new_block', tx=tx, ts_date=ts_date, time_from_now=tx.get_time_from_now()) else: self.log.info('New transaction found', tag='new_tx', tx=tx, ts_date=ts_date, time_from_now=tx.get_time_from_now()) if propagate_to_peers: # Propagate to our peers. self.connections.send_tx_to_peers(tx) if self.wallet: # TODO Remove it and use pubsub instead. self.wallet.on_new_tx(tx) # Publish to pubsub manager the new tx accepted self.pubsub.publish(HathorEvents.NETWORK_NEW_TX_ACCEPTED, tx=tx) return True
def on_new_tx(self, tx: BaseTransaction, *, conn: Optional[HathorProtocol] = None, quiet: bool = False, fails_silently: bool = True, propagate_to_peers: bool = True, skip_block_weight_verification: bool = False) -> bool: """This method is called when any transaction arrive. If `fails_silently` is False, it may raise either InvalidNewTransaction or TxValidationError. :return: True if the transaction was accepted :rtype: bool """ assert tx.hash is not None if self.state != self.NodeState.INITIALIZING: if self.tx_storage.transaction_exists(tx.hash): if not fails_silently: raise InvalidNewTransaction( 'Transaction already exists {}'.format(tx.hash_hex)) self.log.debug('on_new_tx(): Transaction already exists', tx=tx.hash_hex) return False if self.state != self.NodeState.INITIALIZING or self._full_verification: try: assert self.validate_new_tx( tx, skip_block_weight_verification= skip_block_weight_verification) is True except (InvalidNewTransaction, TxValidationError): # Discard invalid Transaction/block. self.log.debug('tx/block discarded', tx=tx, exc_info=True) if not fails_silently: raise return False if self.state != self.NodeState.INITIALIZING: self.tx_storage.save_transaction(tx) else: self.tx_storage._add_to_cache(tx) if self._full_verification: tx.reset_metadata() else: # When doing a fast init, we don't update the consensus, so we must trust the data on the metadata # For transactions, we don't store them on the tips index if they are voided # We have to execute _add_to_cache before because _del_from_cache does not remove from all indexes metadata = tx.get_metadata() if not tx.is_block and metadata.voided_by: self.tx_storage._del_from_cache(tx) if self.state != self.NodeState.INITIALIZING or self._full_verification: try: tx.update_initial_metadata() self.consensus_algorithm.update(tx) except Exception: self.log.exception('unexpected error when processing tx', tx=tx) self.tx_storage.remove_transaction(tx) raise if not quiet: ts_date = datetime.datetime.fromtimestamp(tx.timestamp) if tx.is_block: self.log.info('new block', tx=tx, ts_date=ts_date, time_from_now=tx.get_time_from_now()) else: self.log.info('new tx', tx=tx, ts_date=ts_date, time_from_now=tx.get_time_from_now()) if propagate_to_peers: # Propagate to our peers. self.connections.send_tx_to_peers(tx) if self.wallet: # TODO Remove it and use pubsub instead. self.wallet.on_new_tx(tx) # Publish to pubsub manager the new tx accepted self.pubsub.publish(HathorEvents.NETWORK_NEW_TX_ACCEPTED, tx=tx) return True