def message(self, pubnub, message_obj):
        print(
            f"\n -- Channel: {message_obj.channel} | Message: {message_obj.message}"
        )

        if (message_obj.channel == CHANNELS["BLOCK"]):
            prospective_block = Block.deserialize_from_json(
                message_obj.message)
            prospective_chain = self.blockchain.chain[:]
            prospective_chain.append(prospective_block)

            try:
                self.blockchain.surrogate_chain(prospective_chain)
                # purge recorded Tx from Pool
                self.transaction_pool.purge(self.blockchain)
                print(f"\n -- Chain surrogation successful.")
            except Exception as err:
                print(f"\n -- Chain surrogation failed. See: {err}")

        elif (message_obj.channel == CHANNELS["TRANSACTION"]):
            transaction = Transaction.deserialize_from_json(
                message_obj.message)
            self.transaction_pool.set_transaction(transaction)
            print(
                "\n -- New transaction successfully broadcast, added to the transaction pool."
            )
    def is_tx_chain_valid(blockchain):
        """
        Validate incoming blockchain comprised of blocks with Tx therein qua the following ruleset:
            - each Tx occurs once in the blockchain (i.e. 'double spend')
            - there is only one valid reward Tx per block 
            - transaction obj must be intrinsically valid
        """
        # Tx tracked by id, raise if duplicate
        tx_tracking_pool = set()
        # unwrap blockchain, unwrap blocks therein, deserialize ea block's Tx and parse them
        for i in range(len(blockchain)):
            block = blockchain[i]
            mining_reward_extant = False
            for serialized_tx in block.data:
                deserialized_tx = Transaction.deserialize_from_json(
                    serialized_tx)

                # if Tx already exists
                if (deserialized_tx.id in tx_tracking_pool):
                    raise Exception(
                        f"Transaction {deserialized_tx.id} is not unique; this transaction is therefore invalid."
                    )
                # add Tx to tracking pool
                tx_tracking_pool.add(deserialized_tx.id)

                # if Tx is a block reward, only validate against reward fields
                if (deserialized_tx.input == MINING_REWARD_INPUT):
                    if (mining_reward_extant):
                        raise Exception(f"""
                            There can only be one mining reward per block. 
                            Evaluation of block with hash: {block.hash} recommended."""
                                        )
                    mining_reward_extant = True
                else:
                    # recalc balance after every Tx to prevent input tamper
                    blockchain_provenance = Blockchain()
                    blockchain_provenance.chain = blockchain[0:i]
                    balance_provenance = Wallet.calculate_balance(
                        blockchain_provenance,
                        deserialized_tx.input["address"])

                    if (balance_provenance != deserialized_tx.input["amount"]):
                        raise Exception(
                            f"Transaction {deserialized_tx.id} contains an invalid input amount."
                        )
                # last, run validator to check format
                Transaction.is_tx_valid(deserialized_tx)