mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 13:21:10 +00:00
Moves Block to frame_system instead of construct_runtime and removes Header and BlockNumber (#14437)
* Initial setup * Adds node block * Uses UncheckedExtrinsic and removes Where section * Updates frame_system to use Block * Adds deprecation warning * Fixes pallet-timestamp * Removes Header and BlockNumber * Addresses review comments * Addresses review comments * Adds comment about compiler bug * Removes where clause * Refactors code * Fixes errors in cargo check * Fixes errors in cargo check * Fixes warnings in cargo check * Formatting * Fixes construct_runtime tests * Uses import instead of full path for BlockNumber * Uses import instead of full path for Header * Formatting * Fixes construct_runtime tests * Fixes imports in benchmarks * Formatting * Fixes construct_runtime tests * Formatting * Minor updates * Fixes construct_runtime ui tests * Fixes construct_runtime ui tests with 1.70 * Fixes docs * Fixes docs * Adds u128 mock block type * Fixes split example * fixes for cumulus * ".git/.scripts/commands/fmt/fmt.sh" * Updates new tests * Fixes fully-qualified path in few places * Formatting * Update frame/examples/default-config/src/lib.rs Co-authored-by: Juan <juangirini@gmail.com> * Update frame/support/procedural/src/construct_runtime/mod.rs Co-authored-by: Juan <juangirini@gmail.com> * ".git/.scripts/commands/fmt/fmt.sh" * Addresses some review comments * Fixes build * ".git/.scripts/commands/fmt/fmt.sh" * Update frame/democracy/src/lib.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update frame/democracy/src/lib.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update frame/support/procedural/src/construct_runtime/mod.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update frame/support/procedural/src/construct_runtime/mod.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Addresses review comments * Updates trait bounds * Minor fix * ".git/.scripts/commands/fmt/fmt.sh" * Removes unnecessary bound * ".git/.scripts/commands/fmt/fmt.sh" * Updates test * Fixes build * Adds a bound for header * ".git/.scripts/commands/fmt/fmt.sh" * Removes where block * Minor fix * Minor fix * Fixes tests * ".git/.scripts/commands/update-ui/update-ui.sh" 1.70 * Updates test * Update primitives/runtime/src/traits.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Update primitives/runtime/src/traits.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Updates doc * Updates doc --------- Co-authored-by: command-bot <> Co-authored-by: Juan <juangirini@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
@@ -24,7 +24,7 @@ use frame_support::{
|
||||
assert_noop, assert_ok,
|
||||
traits::{Currency, EnsureOrigin, Get, OnInitialize, UnfilteredDispatchable},
|
||||
};
|
||||
use frame_system::RawOrigin;
|
||||
use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{traits::Bounded, BoundedVec};
|
||||
|
||||
@@ -258,7 +258,7 @@ benchmarks! {
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
Blacklist::<T>::insert(proposal.hash(), (T::BlockNumber::zero(), addresses));
|
||||
Blacklist::<T>::insert(proposal.hash(), (BlockNumberFor::<T>::zero(), addresses));
|
||||
}: _<T::RuntimeOrigin>(origin, proposal)
|
||||
verify {
|
||||
// External proposal created
|
||||
@@ -332,7 +332,7 @@ benchmarks! {
|
||||
vetoers.try_push(account::<T::AccountId>("vetoer", i, SEED)).unwrap();
|
||||
}
|
||||
vetoers.sort();
|
||||
Blacklist::<T>::insert(proposal_hash, (T::BlockNumber::zero(), vetoers));
|
||||
Blacklist::<T>::insert(proposal_hash, (BlockNumberFor::<T>::zero(), vetoers));
|
||||
|
||||
let origin = T::VetoOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
ensure!(NextExternal::<T>::get().is_some(), "no external proposal");
|
||||
@@ -816,7 +816,7 @@ benchmarks! {
|
||||
// create not ongoing referendum.
|
||||
ReferendumInfoOf::<T>::insert(
|
||||
0,
|
||||
ReferendumInfo::Finished { end: T::BlockNumber::zero(), approved: true },
|
||||
ReferendumInfo::Finished { end: BlockNumberFor::<T>::zero(), approved: true },
|
||||
);
|
||||
let owner = MetadataOwner::Referendum(0);
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
@@ -833,7 +833,7 @@ benchmarks! {
|
||||
// create not ongoing referendum.
|
||||
ReferendumInfoOf::<T>::insert(
|
||||
0,
|
||||
ReferendumInfo::Finished { end: T::BlockNumber::zero(), approved: true },
|
||||
ReferendumInfo::Finished { end: BlockNumberFor::<T>::zero(), approved: true },
|
||||
);
|
||||
let owner = MetadataOwner::Referendum(0);
|
||||
let hash = note_preimage::<T>();
|
||||
|
||||
@@ -165,7 +165,7 @@ use frame_support::{
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::pallet_prelude::OriginFor;
|
||||
use frame_system::pallet_prelude::{BlockNumberFor, OriginFor};
|
||||
use sp_runtime::{
|
||||
traits::{Bounded as ArithBounded, One, Saturating, StaticLookup, Zero},
|
||||
ArithmeticError, DispatchError, DispatchResult,
|
||||
@@ -226,14 +226,14 @@ pub mod pallet {
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// The Scheduler.
|
||||
type Scheduler: ScheduleNamed<Self::BlockNumber, CallOf<Self>, Self::PalletsOrigin>;
|
||||
type Scheduler: ScheduleNamed<BlockNumberFor<Self>, CallOf<Self>, Self::PalletsOrigin>;
|
||||
|
||||
/// The Preimage provider.
|
||||
type Preimages: QueryPreimage + StorePreimage;
|
||||
|
||||
/// Currency type for this pallet.
|
||||
type Currency: ReservableCurrency<Self::AccountId>
|
||||
+ LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>;
|
||||
+ LockableCurrency<Self::AccountId, Moment = BlockNumberFor<Self>>;
|
||||
|
||||
/// The period between a proposal being approved and enacted.
|
||||
///
|
||||
@@ -241,22 +241,22 @@ pub mod pallet {
|
||||
/// voting stakers have an opportunity to remove themselves from the system in the case
|
||||
/// where they are on the losing side of a vote.
|
||||
#[pallet::constant]
|
||||
type EnactmentPeriod: Get<Self::BlockNumber>;
|
||||
type EnactmentPeriod: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// How often (in blocks) new public referenda are launched.
|
||||
#[pallet::constant]
|
||||
type LaunchPeriod: Get<Self::BlockNumber>;
|
||||
type LaunchPeriod: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// How often (in blocks) to check for new votes.
|
||||
#[pallet::constant]
|
||||
type VotingPeriod: Get<Self::BlockNumber>;
|
||||
type VotingPeriod: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// The minimum period of vote locking.
|
||||
///
|
||||
/// It should be no shorter than enactment period to ensure that in the case of an approval,
|
||||
/// those successful voters are locked into the consequences that their votes entail.
|
||||
#[pallet::constant]
|
||||
type VoteLockingPeriod: Get<Self::BlockNumber>;
|
||||
type VoteLockingPeriod: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// The minimum amount to be used as a deposit for a public referendum proposal.
|
||||
#[pallet::constant]
|
||||
@@ -270,11 +270,11 @@ pub mod pallet {
|
||||
|
||||
/// Minimum voting period allowed for a fast-track referendum.
|
||||
#[pallet::constant]
|
||||
type FastTrackVotingPeriod: Get<Self::BlockNumber>;
|
||||
type FastTrackVotingPeriod: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// Period in blocks where an external proposal may not be re-submitted after being vetoed.
|
||||
#[pallet::constant]
|
||||
type CooloffPeriod: Get<Self::BlockNumber>;
|
||||
type CooloffPeriod: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// The maximum number of votes for an account.
|
||||
///
|
||||
@@ -387,7 +387,7 @@ pub mod pallet {
|
||||
_,
|
||||
Twox64Concat,
|
||||
ReferendumIndex,
|
||||
ReferendumInfo<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>,
|
||||
ReferendumInfo<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>,
|
||||
>;
|
||||
|
||||
/// All votes for a particular voter. We store the balance for the number of votes that we
|
||||
@@ -399,7 +399,7 @@ pub mod pallet {
|
||||
_,
|
||||
Twox64Concat,
|
||||
T::AccountId,
|
||||
Voting<BalanceOf<T>, T::AccountId, T::BlockNumber, T::MaxVotes>,
|
||||
Voting<BalanceOf<T>, T::AccountId, BlockNumberFor<T>, T::MaxVotes>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
@@ -422,7 +422,7 @@ pub mod pallet {
|
||||
_,
|
||||
Identity,
|
||||
H256,
|
||||
(T::BlockNumber, BoundedVec<T::AccountId, T::MaxBlacklisted>),
|
||||
(BlockNumberFor<T>, BoundedVec<T::AccountId, T::MaxBlacklisted>),
|
||||
>;
|
||||
|
||||
/// Record of all proposals that have been subject to emergency cancellation.
|
||||
@@ -476,7 +476,7 @@ pub mod pallet {
|
||||
/// An account has cancelled a previous delegation operation.
|
||||
Undelegated { account: T::AccountId },
|
||||
/// An external proposal has been vetoed.
|
||||
Vetoed { who: T::AccountId, proposal_hash: H256, until: T::BlockNumber },
|
||||
Vetoed { who: T::AccountId, proposal_hash: H256, until: BlockNumberFor<T> },
|
||||
/// A proposal_hash has been blacklisted permanently.
|
||||
Blacklisted { proposal_hash: H256 },
|
||||
/// An account has voted in a referendum
|
||||
@@ -566,7 +566,7 @@ pub mod pallet {
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
/// Weight: see `begin_block`
|
||||
fn on_initialize(n: T::BlockNumber) -> Weight {
|
||||
fn on_initialize(n: BlockNumberFor<T>) -> Weight {
|
||||
Self::begin_block(n)
|
||||
}
|
||||
}
|
||||
@@ -776,8 +776,8 @@ pub mod pallet {
|
||||
pub fn fast_track(
|
||||
origin: OriginFor<T>,
|
||||
proposal_hash: H256,
|
||||
voting_period: T::BlockNumber,
|
||||
delay: T::BlockNumber,
|
||||
voting_period: BlockNumberFor<T>,
|
||||
delay: BlockNumberFor<T>,
|
||||
) -> DispatchResult {
|
||||
// Rather complicated bit of code to ensure that either:
|
||||
// - `voting_period` is at least `FastTrackVotingPeriod` and `origin` is
|
||||
@@ -795,7 +795,7 @@ pub mod pallet {
|
||||
ensure!(T::InstantAllowed::get(), Error::<T>::InstantNotAllowed);
|
||||
}
|
||||
|
||||
ensure!(voting_period > T::BlockNumber::zero(), Error::<T>::VotingPeriodLow);
|
||||
ensure!(voting_period > Zero::zero(), Error::<T>::VotingPeriodLow);
|
||||
let (ext_proposal, threshold) =
|
||||
<NextExternal<T>>::get().ok_or(Error::<T>::ProposalMissing)?;
|
||||
ensure!(
|
||||
@@ -1048,7 +1048,8 @@ pub mod pallet {
|
||||
T::BlacklistOrigin::ensure_origin(origin)?;
|
||||
|
||||
// Insert the proposal into the blacklist.
|
||||
let permanent = (T::BlockNumber::max_value(), BoundedVec::<T::AccountId, _>::default());
|
||||
let permanent =
|
||||
(BlockNumberFor::<T>::max_value(), BoundedVec::<T::AccountId, _>::default());
|
||||
Blacklist::<T>::insert(&proposal_hash, permanent);
|
||||
|
||||
// Remove the queued proposal, if it's there.
|
||||
@@ -1201,17 +1202,19 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// Get all referenda ready for tally at block `n`.
|
||||
pub fn maturing_referenda_at(
|
||||
n: T::BlockNumber,
|
||||
) -> Vec<(ReferendumIndex, ReferendumStatus<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>)> {
|
||||
n: BlockNumberFor<T>,
|
||||
) -> Vec<(ReferendumIndex, ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>)>
|
||||
{
|
||||
let next = Self::lowest_unbaked();
|
||||
let last = Self::referendum_count();
|
||||
Self::maturing_referenda_at_inner(n, next..last)
|
||||
}
|
||||
|
||||
fn maturing_referenda_at_inner(
|
||||
n: T::BlockNumber,
|
||||
n: BlockNumberFor<T>,
|
||||
range: core::ops::Range<PropIndex>,
|
||||
) -> Vec<(ReferendumIndex, ReferendumStatus<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>)> {
|
||||
) -> Vec<(ReferendumIndex, ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>)>
|
||||
{
|
||||
range
|
||||
.into_iter()
|
||||
.map(|i| (i, Self::referendum_info(i)))
|
||||
@@ -1229,7 +1232,7 @@ impl<T: Config> Pallet<T> {
|
||||
pub fn internal_start_referendum(
|
||||
proposal: BoundedCallOf<T>,
|
||||
threshold: VoteThreshold,
|
||||
delay: T::BlockNumber,
|
||||
delay: BlockNumberFor<T>,
|
||||
) -> ReferendumIndex {
|
||||
<Pallet<T>>::inject_referendum(
|
||||
<frame_system::Pallet<T>>::block_number().saturating_add(T::VotingPeriod::get()),
|
||||
@@ -1250,8 +1253,9 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// Ok if the given referendum is active, Err otherwise
|
||||
fn ensure_ongoing(
|
||||
r: ReferendumInfo<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>,
|
||||
) -> Result<ReferendumStatus<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>, DispatchError> {
|
||||
r: ReferendumInfo<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>,
|
||||
) -> Result<ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>, DispatchError>
|
||||
{
|
||||
match r {
|
||||
ReferendumInfo::Ongoing(s) => Ok(s),
|
||||
_ => Err(Error::<T>::ReferendumInvalid.into()),
|
||||
@@ -1260,7 +1264,8 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
fn referendum_status(
|
||||
ref_index: ReferendumIndex,
|
||||
) -> Result<ReferendumStatus<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>, DispatchError> {
|
||||
) -> Result<ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>, DispatchError>
|
||||
{
|
||||
let info = ReferendumInfoOf::<T>::get(ref_index).ok_or(Error::<T>::ReferendumInvalid)?;
|
||||
Self::ensure_ongoing(info)
|
||||
}
|
||||
@@ -1515,10 +1520,10 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// Start a referendum
|
||||
fn inject_referendum(
|
||||
end: T::BlockNumber,
|
||||
end: BlockNumberFor<T>,
|
||||
proposal: BoundedCallOf<T>,
|
||||
threshold: VoteThreshold,
|
||||
delay: T::BlockNumber,
|
||||
delay: BlockNumberFor<T>,
|
||||
) -> ReferendumIndex {
|
||||
let ref_index = Self::referendum_count();
|
||||
ReferendumCount::<T>::put(ref_index + 1);
|
||||
@@ -1531,7 +1536,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// Table the next waiting proposal for a vote.
|
||||
fn launch_next(now: T::BlockNumber) -> DispatchResult {
|
||||
fn launch_next(now: BlockNumberFor<T>) -> DispatchResult {
|
||||
if LastTabledWasExternal::<T>::take() {
|
||||
Self::launch_public(now).or_else(|_| Self::launch_external(now))
|
||||
} else {
|
||||
@@ -1541,7 +1546,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// Table the waiting external proposal for a vote, if there is one.
|
||||
fn launch_external(now: T::BlockNumber) -> DispatchResult {
|
||||
fn launch_external(now: BlockNumberFor<T>) -> DispatchResult {
|
||||
if let Some((proposal, threshold)) = <NextExternal<T>>::take() {
|
||||
LastTabledWasExternal::<T>::put(true);
|
||||
Self::deposit_event(Event::<T>::ExternalTabled);
|
||||
@@ -1559,7 +1564,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// Table the waiting public proposal with the highest backing for a vote.
|
||||
fn launch_public(now: T::BlockNumber) -> DispatchResult {
|
||||
fn launch_public(now: BlockNumberFor<T>) -> DispatchResult {
|
||||
let mut public_props = Self::public_props();
|
||||
if let Some((winner_index, _)) = public_props.iter().enumerate().max_by_key(
|
||||
// defensive only: All current public proposals have an amount locked
|
||||
@@ -1592,9 +1597,9 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
fn bake_referendum(
|
||||
now: T::BlockNumber,
|
||||
now: BlockNumberFor<T>,
|
||||
index: ReferendumIndex,
|
||||
status: ReferendumStatus<T::BlockNumber, BoundedCallOf<T>, BalanceOf<T>>,
|
||||
status: ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>,
|
||||
) -> bool {
|
||||
let total_issuance = T::Currency::total_issuance();
|
||||
let approved = status.threshold.approved(status.tally, total_issuance);
|
||||
@@ -1629,7 +1634,7 @@ impl<T: Config> Pallet<T> {
|
||||
/// ## Complexity:
|
||||
/// If a referendum is launched or maturing, this will take full block weight if queue is not
|
||||
/// empty. Otherwise, `O(R)` where `R` is the number of unbaked referenda.
|
||||
fn begin_block(now: T::BlockNumber) -> Weight {
|
||||
fn begin_block(now: BlockNumberFor<T>) -> Weight {
|
||||
let max_block_weight = T::BlockWeights::get().max_block;
|
||||
let mut weight = Weight::zero();
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
use crate::*;
|
||||
use frame_support::{pallet_prelude::*, storage_alias, traits::OnRuntimeUpgrade, BoundedVec};
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
use sp_core::H256;
|
||||
|
||||
/// The log target.
|
||||
@@ -45,11 +46,7 @@ mod v0 {
|
||||
Pallet<T>,
|
||||
frame_support::Twox64Concat,
|
||||
ReferendumIndex,
|
||||
ReferendumInfo<
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
<T as frame_system::Config>::Hash,
|
||||
BalanceOf<T>,
|
||||
>,
|
||||
ReferendumInfo<BlockNumberFor<T>, <T as frame_system::Config>::Hash, BalanceOf<T>>,
|
||||
>;
|
||||
}
|
||||
|
||||
@@ -87,7 +84,7 @@ pub mod v1 {
|
||||
}
|
||||
|
||||
ReferendumInfoOf::<T>::translate(
|
||||
|index, old: ReferendumInfo<T::BlockNumber, T::Hash, BalanceOf<T>>| {
|
||||
|index, old: ReferendumInfo<BlockNumberFor<T>, T::Hash, BalanceOf<T>>| {
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
log::info!(target: TARGET, "migrating referendum #{:?}", &index);
|
||||
Some(match old {
|
||||
|
||||
@@ -31,7 +31,6 @@ use frame_system::{EnsureRoot, EnsureSigned, EnsureSignedBy};
|
||||
use pallet_balances::{BalanceLock, Error as BalancesError};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header,
|
||||
traits::{BadOrigin, BlakeTwo256, Hash, IdentityLookup},
|
||||
BuildStorage, Perbill,
|
||||
};
|
||||
@@ -51,14 +50,10 @@ const NAY: Vote = Vote { aye: false, conviction: Conviction::None };
|
||||
const BIG_AYE: Vote = Vote { aye: true, conviction: Conviction::Locked1x };
|
||||
const BIG_NAY: Vote = Vote { aye: false, conviction: Conviction::Locked1x };
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum Test where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic,
|
||||
pub enum Test
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
@@ -89,13 +84,12 @@ impl frame_system::Config for Test {
|
||||
type DbWeight = ();
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Block = Block;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type BlockHashCount = ConstU64<250>;
|
||||
type Version = ();
|
||||
|
||||
Reference in New Issue
Block a user