Какова функция `<T>` в субстрате `fn deposit_event<T>() = default`?

Что касается семинара по предметам коллекционирования субстратов, <T> на самом деле делать и ссылаться на fn deposit_event<T>() = default;? Могу ли я опустить это, когда мой Event не включает в себя, например, AccountId?

1 ответ

Решение

В контексте Субстрата есть несколько вещей, на которые нужно ответить.

Общие типы

Каждый модуль субстрата имеет возможность определять пользовательские типы, необходимые для модуля, и все они необходимы для реализации некоторых характеристик. Вместо того, чтобы строго определять эти типы, использование признаков позволяет нам гарантировать, что типы имеют определенные свойства, но не ограничены тем, каким может быть тип. Эти определения общих типов живут в 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,

Другие вопросы по тегам