Files
pezkuwi-subxt/substrate/frame/indices/src/lib.rs
T
Denis Pisarev be5dc02d3b Fail docs on warnings (#5923)
* change (ci): docs job optimized; runs every commit; fails on warnings

* change (ci): rename jobs; temporary allow failing

* change (ci): better warnings filtering

* fix (ci): hotfix Docker release

* test (ci): run docs job with flags

* test (ci): pwd fails

* change (ci): pass just //doc dir as an artifact; debug

* change (ci): return to the previous structure; undebug

* change (ci): typo

* rebase on upstream 2

* fix the jobname

* Fix some warnings (#7079)

* Partial fix for transaction priority (#7034)

* Partial fix for priority stuff.

* Small fix

* Fix tests.

* Update frame/transaction-payment/src/lib.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Better doc

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* What happens if we remove wat? (#7056)

* What happens if we remove wat?

* Update Cargo.lock

* Make SlashingSpans Public (#6961)

* Make SlashingSpans Public

Offchain Applications will often need to inspect this type because it is directly used in staking election, thus worthy of being `pub`. Rest of the slashing api can remain private, only this and the `fn last_non_zero_slash()` of `SlashingSpans` are of interest.

* Update frame/staking/src/lib.rs

* client/authority-discovery/src/service: Improve docs (#7059)

* Decrease poll interval (#7063)

* Remove unused code (#7027)

Signed-off-by: Jimmy Chu <jimmychu0807@gmail.com>

* Disambiguate `BlockNumber` type in `decl_module` (#7061)

* Disambiguate `BlockNumber` type in `decl_module`

* fix `frame-support-tests`

* fix ui tests

* fix trait order

* Implement `FromStr` for `Ss58AddressFormat` (#7068)

* Implement `FromStr` for `Ss58AddressFormat`

* Update primitives/core/src/crypto.rs

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* Set reserved nodes with offchain worker. (#6996)

* add offchain worker api to set reserved nodes.

* new offchain api to get node public key.

* node public key from converter

* refactor set reserved nodes ocw api.

* new ndoe authorization pallet

* remove unnecessary clone and more.

* more

* tests for node authorization pallet

* remove dependency

* fix build

* more tests.

* refactor

* Update primitives/core/src/offchain/testing.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update frame/node-authorization/src/lib.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update frame/node-authorization/src/lib.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update frame/node-authorization/src/lib.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* format code

* expose NetworkService

* remove NetworkStateInfo in offchain

* replace NodePublicKey with PeerId.

* set max length of peer id.

* clear more

* use BTreeSet for set of peers.

* decode opaque peer id.

* extract NetworkProvider for client offchain.

* use OpaquePeerId in node authorization pallet.

* fix test

* better documentation

* fix test

* doc

* more fix

* Update primitives/core/src/offchain/mod.rs

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* Update client/offchain/src/api.rs

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* derive serialize and deserialize

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* Fix some warnings

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Sergei Shulepov <sergei@parity.io>
Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: s3krit <pugh@s3kr.it>
Co-authored-by: Jimmy Chu <jimmy@parity.io>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: kaichao <kaichaosuna@gmail.com>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* Fix more doc errors

* More doc fixes

* Remove subdb to make `rustdoc` happy

* Make the line length check happy

* Fix compilation error

* Another try

* Allow unused

Co-authored-by: Dan Forbes <dan@danforbes.dev>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Sergei Shulepov <sergei@parity.io>
Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: s3krit <pugh@s3kr.it>
Co-authored-by: Jimmy Chu <jimmy@parity.io>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: kaichao <kaichaosuna@gmail.com>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-authored-by: Bastian Köcher <git@kchr.de>
2020-09-11 17:39:16 +02:00

331 lines
11 KiB
Rust

// This file is part of Substrate.
// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! An index is a short form of an address. This module handles allocation
//! of indices for a newly created accounts.
#![cfg_attr(not(feature = "std"), no_std)]
use sp_std::prelude::*;
use codec::Codec;
use sp_runtime::traits::{
StaticLookup, Member, LookupError, Zero, Saturating, AtLeast32Bit
};
use frame_support::{Parameter, decl_module, decl_error, decl_event, decl_storage, ensure};
use frame_support::dispatch::DispatchResult;
use frame_support::traits::{Currency, ReservableCurrency, Get, BalanceStatus::Reserved};
use frame_support::weights::{Weight, constants::WEIGHT_PER_MICROS};
use frame_system::{ensure_signed, ensure_root};
use self::address::Address as RawAddress;
mod mock;
pub mod address;
mod tests;
mod benchmarking;
pub type Address<T> = RawAddress<<T as frame_system::Trait>::AccountId, <T as Trait>::AccountIndex>;
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
pub trait WeightInfo {
fn claim(i: u32, ) -> Weight;
fn transfer(i: u32, ) -> Weight;
fn free(i: u32, ) -> Weight;
fn force_transfer(i: u32, ) -> Weight;
fn freeze(i: u32, ) -> Weight;
}
impl WeightInfo for () {
fn claim(_i: u32, ) -> Weight { 1_000_000_000 }
fn transfer(_i: u32, ) -> Weight { 1_000_000_000 }
fn free(_i: u32, ) -> Weight { 1_000_000_000 }
fn force_transfer(_i: u32, ) -> Weight { 1_000_000_000 }
fn freeze(_i: u32, ) -> Weight { 1_000_000_000 }
}
/// The module's config trait.
pub trait Trait: frame_system::Trait {
/// Type used for storing an account's index; implies the maximum number of accounts the system
/// can hold.
type AccountIndex: Parameter + Member + Codec + Default + AtLeast32Bit + Copy;
/// The currency trait.
type Currency: ReservableCurrency<Self::AccountId>;
/// The deposit needed for reserving an index.
type Deposit: Get<BalanceOf<Self>>;
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
decl_storage! {
trait Store for Module<T: Trait> as Indices {
/// The lookup from index to account.
pub Accounts build(|config: &GenesisConfig<T>|
config.indices.iter()
.cloned()
.map(|(a, b)| (a, (b, Zero::zero(), false)))
.collect::<Vec<_>>()
): map hasher(blake2_128_concat) T::AccountIndex => Option<(T::AccountId, BalanceOf<T>, bool)>;
}
add_extra_genesis {
config(indices): Vec<(T::AccountIndex, T::AccountId)>;
}
}
decl_event!(
pub enum Event<T> where
<T as frame_system::Trait>::AccountId,
<T as Trait>::AccountIndex
{
/// A account index was assigned. \[who, index\]
IndexAssigned(AccountId, AccountIndex),
/// A account index has been freed up (unassigned). \[index\]
IndexFreed(AccountIndex),
/// A account index has been frozen to its current account ID. \[who, index\]
IndexFrozen(AccountIndex, AccountId),
}
);
decl_error! {
pub enum Error for Module<T: Trait> {
/// The index was not already assigned.
NotAssigned,
/// The index is assigned to another account.
NotOwner,
/// The index was not available.
InUse,
/// The source and destination accounts are identical.
NotTransfer,
/// The index is permanent and may not be freed/changed.
Permanent,
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin, system = frame_system {
/// The deposit needed for reserving an index.
const Deposit: BalanceOf<T> = T::Deposit::get();
fn deposit_event() = default;
/// Assign an previously unassigned index.
///
/// Payment: `Deposit` is reserved from the sender account.
///
/// The dispatch origin for this call must be _Signed_.
///
/// - `index`: the index to be claimed. This must not be in use.
///
/// Emits `IndexAssigned` if successful.
///
/// # <weight>
/// - `O(1)`.
/// - One storage mutation (codec `O(1)`).
/// - One reserve operation.
/// - One event.
/// -------------------
/// - Base Weight: 28.69 µs
/// - DB Weight: 1 Read/Write (Accounts)
/// # </weight>
#[weight = T::DbWeight::get().reads_writes(1, 1) + 30 * WEIGHT_PER_MICROS]
fn claim(origin, index: T::AccountIndex) {
let who = ensure_signed(origin)?;
Accounts::<T>::try_mutate(index, |maybe_value| {
ensure!(maybe_value.is_none(), Error::<T>::InUse);
*maybe_value = Some((who.clone(), T::Deposit::get(), false));
T::Currency::reserve(&who, T::Deposit::get())
})?;
Self::deposit_event(RawEvent::IndexAssigned(who, index));
}
/// Assign an index already owned by the sender to another account. The balance reservation
/// is effectively transferred to the new account.
///
/// The dispatch origin for this call must be _Signed_.
///
/// - `index`: the index to be re-assigned. This must be owned by the sender.
/// - `new`: the new owner of the index. This function is a no-op if it is equal to sender.
///
/// Emits `IndexAssigned` if successful.
///
/// # <weight>
/// - `O(1)`.
/// - One storage mutation (codec `O(1)`).
/// - One transfer operation.
/// - One event.
/// -------------------
/// - Base Weight: 33.74 µs
/// - DB Weight:
/// - Reads: Indices Accounts, System Account (recipient)
/// - Writes: Indices Accounts, System Account (recipient)
/// # </weight>
#[weight = T::DbWeight::get().reads_writes(2, 2) + 35 * WEIGHT_PER_MICROS]
fn transfer(origin, new: T::AccountId, index: T::AccountIndex) {
let who = ensure_signed(origin)?;
ensure!(who != new, Error::<T>::NotTransfer);
Accounts::<T>::try_mutate(index, |maybe_value| -> DispatchResult {
let (account, amount, perm) = maybe_value.take().ok_or(Error::<T>::NotAssigned)?;
ensure!(!perm, Error::<T>::Permanent);
ensure!(&account == &who, Error::<T>::NotOwner);
let lost = T::Currency::repatriate_reserved(&who, &new, amount, Reserved)?;
*maybe_value = Some((new.clone(), amount.saturating_sub(lost), false));
Ok(())
})?;
Self::deposit_event(RawEvent::IndexAssigned(new, index));
}
/// Free up an index owned by the sender.
///
/// Payment: Any previous deposit placed for the index is unreserved in the sender account.
///
/// The dispatch origin for this call must be _Signed_ and the sender must own the index.
///
/// - `index`: the index to be freed. This must be owned by the sender.
///
/// Emits `IndexFreed` if successful.
///
/// # <weight>
/// - `O(1)`.
/// - One storage mutation (codec `O(1)`).
/// - One reserve operation.
/// - One event.
/// -------------------
/// - Base Weight: 25.53 µs
/// - DB Weight: 1 Read/Write (Accounts)
/// # </weight>
#[weight = T::DbWeight::get().reads_writes(1, 1) + 25 * WEIGHT_PER_MICROS]
fn free(origin, index: T::AccountIndex) {
let who = ensure_signed(origin)?;
Accounts::<T>::try_mutate(index, |maybe_value| -> DispatchResult {
let (account, amount, perm) = maybe_value.take().ok_or(Error::<T>::NotAssigned)?;
ensure!(!perm, Error::<T>::Permanent);
ensure!(&account == &who, Error::<T>::NotOwner);
T::Currency::unreserve(&who, amount);
Ok(())
})?;
Self::deposit_event(RawEvent::IndexFreed(index));
}
/// Force an index to an account. This doesn't require a deposit. If the index is already
/// held, then any deposit is reimbursed to its current owner.
///
/// The dispatch origin for this call must be _Root_.
///
/// - `index`: the index to be (re-)assigned.
/// - `new`: the new owner of the index. This function is a no-op if it is equal to sender.
/// - `freeze`: if set to `true`, will freeze the index so it cannot be transferred.
///
/// Emits `IndexAssigned` if successful.
///
/// # <weight>
/// - `O(1)`.
/// - One storage mutation (codec `O(1)`).
/// - Up to one reserve operation.
/// - One event.
/// -------------------
/// - Base Weight: 26.83 µs
/// - DB Weight:
/// - Reads: Indices Accounts, System Account (original owner)
/// - Writes: Indices Accounts, System Account (original owner)
/// # </weight>
#[weight = T::DbWeight::get().reads_writes(2, 2) + 25 * WEIGHT_PER_MICROS]
fn force_transfer(origin, new: T::AccountId, index: T::AccountIndex, freeze: bool) {
ensure_root(origin)?;
Accounts::<T>::mutate(index, |maybe_value| {
if let Some((account, amount, _)) = maybe_value.take() {
T::Currency::unreserve(&account, amount);
}
*maybe_value = Some((new.clone(), Zero::zero(), freeze));
});
Self::deposit_event(RawEvent::IndexAssigned(new, index));
}
/// Freeze an index so it will always point to the sender account. This consumes the deposit.
///
/// The dispatch origin for this call must be _Signed_ and the signing account must have a
/// non-frozen account `index`.
///
/// - `index`: the index to be frozen in place.
///
/// Emits `IndexFrozen` if successful.
///
/// # <weight>
/// - `O(1)`.
/// - One storage mutation (codec `O(1)`).
/// - Up to one slash operation.
/// - One event.
/// -------------------
/// - Base Weight: 30.86 µs
/// - DB Weight: 1 Read/Write (Accounts)
/// # </weight>
#[weight = T::DbWeight::get().reads_writes(1, 1) + 30 * WEIGHT_PER_MICROS]
fn freeze(origin, index: T::AccountIndex) {
let who = ensure_signed(origin)?;
Accounts::<T>::try_mutate(index, |maybe_value| -> DispatchResult {
let (account, amount, perm) = maybe_value.take().ok_or(Error::<T>::NotAssigned)?;
ensure!(!perm, Error::<T>::Permanent);
ensure!(&account == &who, Error::<T>::NotOwner);
T::Currency::slash_reserved(&who, amount);
*maybe_value = Some((account, Zero::zero(), true));
Ok(())
})?;
Self::deposit_event(RawEvent::IndexFrozen(index, who));
}
}
}
impl<T: Trait> Module<T> {
// PUBLIC IMMUTABLES
/// Lookup an T::AccountIndex to get an Id, if there's one there.
pub fn lookup_index(index: T::AccountIndex) -> Option<T::AccountId> {
Accounts::<T>::get(index).map(|x| x.0)
}
/// Lookup an address to get an Id, if there's one there.
pub fn lookup_address(
a: address::Address<T::AccountId, T::AccountIndex>
) -> Option<T::AccountId> {
match a {
address::Address::Id(i) => Some(i),
address::Address::Index(i) => Self::lookup_index(i),
}
}
}
impl<T: Trait> StaticLookup for Module<T> {
type Source = address::Address<T::AccountId, T::AccountIndex>;
type Target = T::AccountId;
fn lookup(a: Self::Source) -> Result<Self::Target, LookupError> {
Self::lookup_address(a).ok_or(LookupError)
}
fn unlookup(a: Self::Target) -> Self::Source {
address::Address::Id(a)
}
}