Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 48564)
+++ src/wp-includes/functions.php	(working copy)
@@ -5156,6 +5156,74 @@
 }
 
 /**
+ * Marks a deprecated option as deprecated and throws a notice.
+ *
+ * Use the {@see 'deprecated_option_used'} action to get the backtrace describing where
+ * the deprecated option was called.
+ *
+ * Default behavior is to trigger a user error if `WP_DEBUG` is true.
+ *
+ * This function is called by the options API functions, and so generally does not
+ * need to be called directly.
+ *
+ * @since 5.5.0
+ * @access private
+ *
+ * @param string $option      The option that was used.
+ * @param string $version     The version of WordPress that deprecated the option.
+ * @param string $replacement Optional. The option that should have been used. Default empty.
+ * @param string $message     Optional. A message regarding the change. Default empty.
+ */
+function _deprecated_option( $option, $version, $replacement = '', $message = '' ) {
+	/**
+	 * Fires when a deprecated option is used.
+	 *
+	 * @since 5.5.0
+	 *
+	 * @param string $hook        The option that was used.
+	 * @param string $replacement The option that should be used as a replacement.
+	 * @param string $version     The version of WordPress that deprecated the option.
+	 * @param string $message     A message regarding the change.
+	 */
+	do_action( 'deprecated_option_used', $option, $replacement, $version, $message );
+
+	/**
+	 * Filters whether to trigger deprecated option errors.
+	 *
+	 * @since 5.5.0
+	 *
+	 * @param bool $trigger Whether to trigger deprecated option errors. Requires
+	 *                      `WP_DEBUG` to be defined true.
+	 */
+	if ( WP_DEBUG && apply_filters( 'deprecated_option_trigger_error', true ) ) {
+		$message = empty( $message ) ? '' : ' ' . $message;
+
+		if ( $replacement ) {
+			trigger_error(
+				sprintf(
+					/* translators: 1: WordPress option name, 2: Version number, 3: Alternative option name. */
+					__( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
+					$option,
+					$version,
+					$replacement
+				) . $message,
+				E_USER_DEPRECATED
+			);
+		} else {
+			trigger_error(
+				sprintf(
+					/* translators: 1: WordPress option name, 2: Version number. */
+					__( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
+					$option,
+					$version
+				) . $message,
+				E_USER_DEPRECATED
+			);
+		}
+	}
+}
+
+/**
  * Mark something as being incorrectly called.
  *
  * There is a hook {@see 'doing_it_wrong_run'} that will be called that can be used
@@ -7627,3 +7695,24 @@
 function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
 	return abs( (float) $expected - (float) $actual ) <= $precision;
 }
+
+/**
+ * Retrieves a list of deprecated options.
+ *
+ * @return array List of deprecated options in the 'old_option_key' => 'new_option_key' format.
+ */
+function get_deprecated_options() {
+	$deprecated_options = array(
+		'blacklist_keys'    => 'blocklist_keys',
+		'comment_whitelist' => 'comment_previously_approved',
+	);
+
+	/**
+	 * Filters the list of deprecated options.
+	 *
+	 * @since 5.5.0
+	 *
+	 * @param array $deprecated_options A list of deprecated options in the 'old_option_key' => 'new_option_key' format.
+	 */
+	return apply_filters( 'deprecated_options', $deprecated_options );
+}
Index: src/wp-includes/option.php
===================================================================
--- src/wp-includes/option.php	(revision 48564)
+++ src/wp-includes/option.php	(working copy)
@@ -35,6 +35,14 @@
 		return false;
 	}
 
+	$is_deprecated      = false;
+	$deprecated_options = get_deprecated_options();
+
+	if ( isset( $deprecated_options[ $option ] ) ) {
+		$deprecated = true;
+		_deprecated_option( $option, '5.5.0', $deprecated_options[ $option ] );
+	}
+
 	/**
 	 * Filters the value of an existing option before it is retrieved.
 	 *
@@ -57,6 +65,11 @@
 	 */
 	$pre = apply_filters( "pre_option_{$option}", false, $option, $default );
 
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		apply_filters( "pre_option_{$deprecated_options[ $option ]}", false, $deprecated_options[ $option ], $default );
+	}
+
 	if ( false !== $pre ) {
 		return $pre;
 	}
@@ -87,7 +100,14 @@
 			 * @param string $option  Option name.
 			 * @param bool   $passed_default Was `get_option()` passed a default value?
 			 */
-			return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
+			$default = apply_filters( "default_option_{$option}", $default, $option, $passed_default );
+
+			if ( $is_deprecated ) {
+				/** This filter is documented in wp-includes/option.php */
+				$default = apply_filters( "default_option_{$deprecated_options[ $option ]}", $default, $deprecated_options[ $option ], $passed_default );
+			}
+
+			return $default;
 		}
 
 		$alloptions = wp_load_alloptions();
@@ -113,7 +133,14 @@
 					wp_cache_set( 'notoptions', $notoptions, 'options' );
 
 					/** This filter is documented in wp-includes/option.php */
-					return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
+					$default = apply_filters( "default_option_{$option}", $default, $option, $passed_default );
+
+					if ( $is_deprecated ) {
+						/** This filter is documented in wp-includes/option.php */
+						$default = apply_filters( "default_option_{$deprecated_options[ $option ]}", $default, $deprecated_options[ $option ], $passed_default );
+					}
+
+					return $default;
 				}
 			}
 		}
@@ -126,7 +153,14 @@
 			$value = $row->option_value;
 		} else {
 			/** This filter is documented in wp-includes/option.php */
-			return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
+			$default = apply_filters( "default_option_{$option}", $default, $option, $passed_default );
+
+			if ( $is_deprecated ) {
+				/** This filter is documented in wp-includes/option.php */
+				$default = apply_filters( "default_option_{$deprecated_options[ $option ]}", $default, $deprecated_options[ $option ], $passed_default );
+			}
+
+			return $default;
 		}
 	}
 
@@ -152,7 +186,14 @@
 	 *                       unserialized prior to being returned.
 	 * @param string $option Option name.
 	 */
-	return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
+	$value = apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
+
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		$default = apply_filters( "option_{$deprecated_options[ $option ]}", maybe_unserialize( $value ), $option );
+	}
+
+	return $value;
 }
 
 /**
@@ -313,6 +354,14 @@
 		return false;
 	}
 
+	$is_deprecated      = false;
+	$deprecated_options = get_deprecated_options();
+
+	if ( isset( $deprecated_options[ $option ] ) ) {
+		$deprecated = true;
+		_deprecated_option( $option, '5.5.0', $deprecated_options[ $option ] );
+	}
+
 	wp_protect_special_option( $option );
 
 	if ( is_object( $value ) ) {
@@ -336,6 +385,11 @@
 	 */
 	$value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );
 
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		$value = apply_filters( "pre_update_option_{$deprecated_options[$option]}", $value, $old_value, $option );
+	}
+
 	/**
 	 * Filters an option before its value is (maybe) serialized and updated.
 	 *
@@ -347,6 +401,11 @@
 	 */
 	$value = apply_filters( 'pre_update_option', $value, $option, $old_value );
 
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		$value = apply_filters( 'pre_update_option', $value, $old_value, $deprecated_options[ $option ] );
+	}
+
 	/*
 	 * If the new and old values are the same, no need to update.
 	 *
@@ -383,6 +442,11 @@
 	 */
 	do_action( 'update_option', $option, $old_value, $value );
 
+	if ( $is_deprecated ) {
+		/** This action is documented in wp-includes/option.php */
+		do_action( 'update_option', $deprecated_options[ $option ], $old_value, $value );
+	}
+
 	$update_args = array(
 		'option_value' => $serialized_value,
 	);
@@ -427,6 +491,11 @@
 	 */
 	do_action( "update_option_{$option}", $old_value, $value, $option );
 
+	if ( $is_deprecated ) {
+		/** This action is documented in wp-includes/option.php */
+		do_action( "update_option_{$deprecated_options[$option]}", $old_value, $value, $deprecated_options[ $option ] );
+	}
+
 	/**
 	 * Fires after the value of an option has been successfully updated.
 	 *
@@ -438,6 +507,11 @@
 	 */
 	do_action( 'updated_option', $option, $old_value, $value );
 
+	if ( $is_deprecated ) {
+		/** This action is documented in wp-includes/option.php */
+		do_action( 'updated_option', $deprecated_options[ $option ], $old_value, $value );
+	}
+
 	return true;
 }
 
@@ -477,6 +551,14 @@
 		return false;
 	}
 
+	$is_deprecated      = false;
+	$deprecated_options = get_deprecated_options();
+
+	if ( isset( $deprecated_options[ $option ] ) ) {
+		$deprecated = true;
+		_deprecated_option( $option, '5.5.0', $deprecated_options[ $option ] );
+	}
+
 	wp_protect_special_option( $option );
 
 	if ( is_object( $value ) ) {
@@ -509,6 +591,11 @@
 	 */
 	do_action( 'add_option', $option, $value );
 
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		do_action( 'add_option', $deprecated_options[ $option ], $value );
+	}
+
 	$result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $serialized_value, $autoload ) );
 	if ( ! $result ) {
 		return false;
@@ -545,6 +632,11 @@
 	 */
 	do_action( "add_option_{$option}", $option, $value );
 
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		do_action( "add_option__{$deprecated_options[ $option ]}", $deprecated_options[ $option ], $value );
+	}
+
 	/**
 	 * Fires after an option has been added.
 	 *
@@ -555,6 +647,11 @@
 	 */
 	do_action( 'added_option', $option, $value );
 
+	if ( $is_deprecated ) {
+		/** This filter is documented in wp-includes/option.php */
+		do_action( 'added_option', $deprecated_options[ $option ], $value );
+	}
+
 	return true;
 }
 
@@ -576,6 +673,14 @@
 		return false;
 	}
 
+	$is_deprecated      = false;
+	$deprecated_options = get_deprecated_options();
+
+	if ( isset( $deprecated_options[ $option ] ) ) {
+		$deprecated = true;
+		_deprecated_option( $option, '5.5.0', $deprecated_options[ $option ] );
+	}
+
 	wp_protect_special_option( $option );
 
 	// Get the ID, if no ID then return.
@@ -620,6 +725,11 @@
 		 */
 		do_action( "delete_option_{$option}", $option );
 
+		if ( $is_deprecated ) {
+			/** This action is documented in wp-includes/option.php */
+			do_action( "delete_option_{$deprecated_options[$option]}", $deprecated_options[ $option ] );
+		}
+
 		/**
 		 * Fires after an option has been deleted.
 		 *
@@ -629,6 +739,11 @@
 		 */
 		do_action( 'deleted_option', $option );
 
+		if ( $is_deprecated ) {
+			/** This action is documented in wp-includes/option.php */
+			do_action( 'deleted_option', $deprecated_options[ $option ] );
+		}
+
 		return true;
 	}
 
