+pub type Scorer = ScorerUsingTime::<DefaultTime>;
+
+/// Time used by [`Scorer`].
+#[cfg(not(feature = "no-std"))]
+pub type DefaultTime = std::time::Instant;
+
+/// Time used by [`Scorer`].
+#[cfg(feature = "no-std")]
+pub type DefaultTime = Eternity;
+
+/// [`routing::Score`] implementation parameterized by [`Time`].
+///
+/// See [`Scorer`] for details.
+///
+/// # Note
+///
+/// Mixing [`Time`] types between serialization and deserialization results in undefined behavior.
+pub struct ScorerUsingTime<T: Time> {
+ params: ScoringParameters,
+ // TODO: Remove entries of closed channels.
+ channel_failures: HashMap<u64, ChannelFailure<T>>,
+}
+
+/// Parameters for configuring [`Scorer`].
+pub struct ScoringParameters {
+ /// A fixed penalty in msats to apply to each channel.
+ pub base_penalty_msat: u64,
+
+ /// A penalty in msats to apply to a channel upon failing to relay a payment.
+ ///
+ /// This accumulates for each failure but may be reduced over time based on
+ /// [`failure_penalty_half_life`].
+ ///
+ /// [`failure_penalty_half_life`]: Self::failure_penalty_half_life
+ pub failure_penalty_msat: u64,
+
+ /// The time required to elapse before any accumulated [`failure_penalty_msat`] penalties are
+ /// cut in half.
+ ///
+ /// # Note
+ ///
+ /// When time is an [`Eternity`], as is default when enabling feature `no-std`, it will never
+ /// elapse. Therefore, this penalty will never decay.
+ ///
+ /// [`failure_penalty_msat`]: Self::failure_penalty_msat
+ pub failure_penalty_half_life: Duration,
+}
+
+impl_writeable_tlv_based!(ScoringParameters, {
+ (0, base_penalty_msat, required),
+ (2, failure_penalty_msat, required),
+ (4, failure_penalty_half_life, required),
+});
+
+/// Accounting for penalties against a channel for failing to relay any payments.
+///
+/// Penalties decay over time, though accumulate as more failures occur.
+struct ChannelFailure<T: Time> {
+ /// Accumulated penalty in msats for the channel as of `last_failed`.
+ undecayed_penalty_msat: u64,
+
+ /// Last time the channel failed. Used to decay `undecayed_penalty_msat`.
+ last_failed: T,