Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Do nothing for zero imbalances (#4089)
Browse files Browse the repository at this point in the history
  • Loading branch information
gavofyork committed Nov 12, 2019
1 parent 4c15d8a commit 6611308
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 14 deletions.
2 changes: 1 addition & 1 deletion node/runtime/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}

pub struct Author;
impl OnUnbalanced<NegativeImbalance> for Author {
fn on_unbalanced(amount: NegativeImbalance) {
fn on_nonzero_unbalanced(amount: NegativeImbalance) {
Balances::resolve_creating(&Authorship::author(), amount);
}
}
Expand Down
16 changes: 14 additions & 2 deletions srml/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ use codec::{Codec, Encode, Decode};
use support::{
StorageValue, Parameter, decl_event, decl_storage, decl_module,
traits::{
UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced,
UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced, TryDrop,
WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement,
Imbalance, SignedImbalance, ReservableCurrency, Get,
},
Expand Down Expand Up @@ -603,7 +603,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
mod imbalances {
use super::{
result, Subtrait, DefaultInstance, Imbalance, Trait, Zero, Instance, Saturating,
StorageValue,
StorageValue, TryDrop,
};
use rstd::mem;

Expand Down Expand Up @@ -631,6 +631,12 @@ mod imbalances {
}
}

impl<T: Trait<I>, I: Instance> TryDrop for PositiveImbalance<T, I> {
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T: Trait<I>, I: Instance> Imbalance<T::Balance> for PositiveImbalance<T, I> {
type Opposite = NegativeImbalance<T, I>;

Expand Down Expand Up @@ -676,6 +682,12 @@ mod imbalances {
}
}

impl<T: Trait<I>, I: Instance> TryDrop for NegativeImbalance<T, I> {
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T: Trait<I>, I: Instance> Imbalance<T::Balance> for NegativeImbalance<T, I> {
type Opposite = PositiveImbalance<T, I>;

Expand Down
29 changes: 26 additions & 3 deletions srml/generic-asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ use codec::{Decode, Encode, HasCompact, Input, Output, Error};

use sr_primitives::RuntimeDebug;
use sr_primitives::traits::{
CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic, Zero, Bounded
CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic,
Zero, Bounded,
};

use rstd::prelude::*;
Expand All @@ -165,7 +166,7 @@ use support::{
decl_event, decl_module, decl_storage, ensure,
traits::{
Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, ReservableCurrency,
SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons,
SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons, TryDrop,
},
Parameter, StorageMap,
};
Expand Down Expand Up @@ -862,7 +863,9 @@ pub trait AssetIdProvider {
// wrapping these imbalanes in a private module is necessary to ensure absolute privacy
// of the inner member.
mod imbalances {
use super::{result, AssetIdProvider, Imbalance, Saturating, StorageMap, Subtrait, Zero};
use super::{
result, AssetIdProvider, Imbalance, Saturating, StorageMap, Subtrait, Zero, TryDrop
};
use rstd::mem;

/// Opaque, move-only struct with private fields that serves as a token denoting that
Expand Down Expand Up @@ -899,6 +902,16 @@ mod imbalances {
}
}

impl<T, U> TryDrop for PositiveImbalance<T, U>
where
T: Subtrait,
U: AssetIdProvider<AssetId = T::AssetId>,
{
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T, U> Imbalance<T::Balance> for PositiveImbalance<T, U>
where
T: Subtrait,
Expand Down Expand Up @@ -948,6 +961,16 @@ mod imbalances {
}
}

impl<T, U> TryDrop for NegativeImbalance<T, U>
where
T: Subtrait,
U: AssetIdProvider<AssetId = T::AssetId>,
{
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T, U> Imbalance<T::Balance> for NegativeImbalance<T, U>
where
T: Subtrait,
Expand Down
26 changes: 19 additions & 7 deletions srml/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,19 @@ pub trait KeyOwnerProofSystem<Key> {
///
/// - Someone got slashed.
/// - Someone paid for a transaction to be included.
pub trait OnUnbalanced<Imbalance> {
pub trait OnUnbalanced<Imbalance: TryDrop> {
/// Handler for some imbalance. Infallible.
fn on_unbalanced(amount: Imbalance);
fn on_unbalanced(amount: Imbalance) {
amount.try_drop().unwrap_or_else(Self::on_nonzero_unbalanced)
}

/// Actually handle a non-zero imbalance. You probably want to implement this rather than
/// `on_unbalanced`.
fn on_nonzero_unbalanced(amount: Imbalance);
}

impl<Imbalance> OnUnbalanced<Imbalance> for () {
fn on_unbalanced(amount: Imbalance) { drop(amount); }
impl<Imbalance: TryDrop> OnUnbalanced<Imbalance> for () {
fn on_nonzero_unbalanced(amount: Imbalance) { drop(amount); }
}

/// Simple boolean for whether an account needs to be kept in existence.
Expand All @@ -153,6 +159,12 @@ pub enum ExistenceRequirement {
AllowDeath,
}

/// A type for which some values make sense to be able to drop without further consideration.
pub trait TryDrop: Sized {
/// Drop an instance cleanly. Only works if its value represents "no-operation".
fn try_drop(self) -> Result<(), Self>;
}

/// A trait for a not-quite Linear Type that tracks an imbalance.
///
/// Functions that alter account balances return an object of this trait to
Expand Down Expand Up @@ -182,14 +194,14 @@ pub enum ExistenceRequirement {
///
/// You can always retrieve the raw balance value using `peek`.
#[must_use]
pub trait Imbalance<Balance>: Sized {
pub trait Imbalance<Balance>: Sized + TryDrop {
/// The oppositely imbalanced type. They come in pairs.
type Opposite: Imbalance<Balance>;

/// The zero imbalance. Can be destroyed with `drop_zero`.
fn zero() -> Self;

/// Drop an instance cleanly. Only works if its `value()` is zero.
/// Drop an instance cleanly. Only works if its `self.value()` is zero.
fn drop_zero(self) -> Result<(), Self>;

/// Consume `self` and return two independent instances; the first
Expand Down Expand Up @@ -297,7 +309,7 @@ impl<
Target2: OnUnbalanced<I>,
> OnUnbalanced<I> for SplitTwoWays<Balance, I, Part1, Target1, Part2, Target2>
{
fn on_unbalanced(amount: I) {
fn on_nonzero_unbalanced(amount: I) {
let total: u32 = Part1::VALUE + Part2::VALUE;
let amount1 = amount.peek().saturating_mul(Part1::VALUE.into()) / total.into();
let (imb1, imb2) = amount.split(amount1);
Expand Down
2 changes: 1 addition & 1 deletion srml/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl<T: Trait> Module<T> {
}

impl<T: Trait> OnUnbalanced<NegativeImbalanceOf<T>> for Module<T> {
fn on_unbalanced(amount: NegativeImbalanceOf<T>) {
fn on_nonzero_unbalanced(amount: NegativeImbalanceOf<T>) {
let numeric_amount = amount.peek();

// Must resolve into existing but better to be safe.
Expand Down

0 comments on commit 6611308

Please sign in to comment.