В контексте Субстрата, здесь есть несколько вещей, на которые нужно ответить.
Универсальные типы
Каждый модуль субстрата имеет возможность определять пользовательские типы, необходимые для модуля, всекоторые необходимы для реализации некоторых черт.Вместо того, чтобы строго определять эти типы, использование признаков позволяет нам гарантировать, что типы имеют определенные свойства, но не ограничены тем, каким может быть тип.Эти определения родовых типов находятся в trait Trait
, который должен быть определен в каждом модуле.
Вот пример пользовательских типов, определенных в модуле system
, который используется впочти все другие модули:
pub trait Trait: 'static + Eq + Clone {
/// The aggregated `Origin` type used by dispatchable calls.
type Origin: ...
/// Account index (aka nonce) type. This stores the number of previous transactions associated with a sender
/// account.
type Index: ...
/// The block number type used by the runtime.
type BlockNumber: ...
/// The output of the `Hashing` function.
type Hash: ...
/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
type Hashing: Hash<Output = Self::Hash>;
/// Collection of (light-client-relevant) logs for a block to be included verbatim in the block header.
type Digest: ...
/// The user account identifier type for the runtime.
type AccountId: ...
/// Converting trait to take a source type and convert to `AccountId`.
///
/// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly
/// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules
/// (e.g. Indices module) may provide more functional/efficient alternatives.
type Lookup: StaticLookup<Target = Self::AccountId>;
/// The block header.
type Header: ...
/// The aggregated event type of the runtime.
type Event: Parameter + Member + From<Event>;
/// A piece of information that can be part of the digest (as a digest item).
type Log: From<Log<Self>> + Into<DigestItemOf<Self>>;
}
В вашем пользовательском модуле вы определите что-то вроде:
/// The module's configuration trait.
pub trait Trait: system::Trait {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
Обратите внимание, что мы определили наш собственный тип Event
, который наш модультеперь мы можем использовать, но у нас есть унаследованные черты от модуля system
(system::Trait
), поэтому мы также можем использовать все эти типы!
Использование универсальных типов
Теперь, когда мы определили некоторые пользовательские типы в нашем модуле времени выполнения, мы можем начать использовать их во всей логике нашего модуля.
Вы всегда увидите строку, похожую на вторую строку в этом фрагменте кода:
decl_storage! {
trait Store for Module<T: Trait> as Sudo {
/// The `AccountId` of the sudo key.
Key get(key) config(): T::AccountId;
}
}
Часть этой строки - макромагия, но, как вы понимаете, мы определяем Module<T: Trait>
.Это означает, что мы присвоили trait Trait
нашего модуля в качестве универсального параметра для Module
под псевдонимом T
.
Таким образом, мы можем затем использовать T
для ссылки на эти специальные типы, как мы делали выше:
T::AccountId
Пройдя полный круг, мы можем получить доступ к этому типу, потому что мы унаследовали его от определения system::Trait
!
Создание макроса депозита события
Чтобы окончательно ответитьна ваш вопрос, функция decl_module!
генерирует тело функции deposit_event
, чтобы избавить вас от написания одного и того же кода снова и снова.
Мы обнаруживаем предварительно определенное имя функции deposit_event
и проверяем= default;
, а затем замените его рабочей deposit_event
функцией.
Однако при генерации этой функции макрос не знает, следует ли ему использовать функцию, в которой событие ввода является универсальным, или вводСобытие не использует дженерики.Таким образом, вам нужно «дать подсказку», сказав deposit_event<T>()
или просто deposit_event()
.
. Затем он создаст правильную версию функции, которая будет работать с типами в вашем модуле.Если в событиях вашего модуля используются универсальные типы, такие как T::AccountId
или T::Balance
, вам также необходимо определить универсальную версию deposit_event
.