code: def get_transaction_by_index(
              self,
              block_number: BlockNumber,
              transaction_index: int,
              transaction_class: Type['BaseTransaction']) -> 'BaseTransaction':
          
          try:
              block_header = self.get_canonical_block_header_by_number(block_number)
          except HeaderNotFound:
              raise TransactionNotFound("Block {} is not in the canonical chain".format(block_number))
          transaction_db = HexaryTrie(self.db, root_hash=block_header.transaction_root)
          encoded_index = rlp.encode(transaction_index)
          if encoded_index in transaction_db:
              encoded_transaction = transaction_db[encoded_index]
              return rlp.decode(encoded_transaction, sedes=transaction_class)
          else:
              raise TransactionNotFound(
                  "No transaction is at index {} of block {}".format(transaction_index, block_number))
docs: Returns the transaction at the specified `transaction_index` from the
          block specified by `block_number` from the canonical chain.
  
          Raises TransactionNotFound if no block