7

在实现我的链逻辑时,我想知道是否要使用事件,因为它们可能会花费节点额外的事件日志存储空间。这里涉及的实际存储成本是多少?日志会在某个时候自动清除吗?

4

2 回答 2

13

运行时事件由系统模块处理。在您自己的模块中,您通常会实现默认deposit_event功能:

从代码内文档:

deposit_event: 用于存放事件的辅助函数。默认行为是deposit_event系统模块调用。但是,您可以为运行时中的事件编写自己的实现。要使用默认行为,请添加fn deposit_event<T>() = default;到您的Module.

如果您查看System 模块代码,您会发现最终调用了一个辅助函数来存储事件:

/// Deposits an event into this block's event record adding this event
/// to the corresponding topic indexes.
///
/// This will update storage entries that correspond to the specified topics.
/// It is expected that light-clients could subscribe to this topics.

pub fn deposit_event_indexed(topics: &[T::Hash], event: T::Event) { ... }

此功能修改了您可以在decl_storage系统模块中找到的三个存储项:

/// Events deposited for the current block.
Events get(events): Vec<EventRecord<T::Event, T::Hash>>;

/// The number of events in the `Events<T>` list.
EventCount get(event_count): EventIndex;

/// Mapping between a topic (represented by T::Hash) and a vector of indexes
/// of events in the `<Events<T>>` list.
EventTopics get(event_topics): double_map hasher(blake2_256) (), blake2_256(T::Hash)
            => Vec<(T::BlockNumber, EventIndex)>;

事件故事的最后一部分可以initialize在系统模块的函数中找到,其中所有这三个项目都被“清理”了:

pub fn initialize( ... ) {
    ...
    <Events<T>>::kill();
    EventCount::kill();
    <EventTopics<T>>::remove_prefix(&());
}

这个initialize函数在每个块开始的执行模块on_initialize中被调用,之前被任何模块调用:

fn initialize_block_impl(
    block_number: &System::BlockNumber,
    parent_hash: &System::Hash,
    extrinsics_root: &System::Hash,
    digest: &Digest<System::Hash>,
) {
    <system::Module<System>>::initialize(block_number, parent_hash, extrinsics_root, digest);
    <AllModules as OnInitialize<System::BlockNumber>>::on_initialize(*block_number);
}

总之,在运行时添加单个 Event 的成本是:

  • 运行deposit_event_indexed函数。
  • 将新项目添加到运行时存储中的两个向量。
  • ...它们在下一个区块开始时被清理,因此存储成本不会增加。
于 2019-07-27T19:24:34.800 回答
2

根据发出的内部数据的类型,事件的创建方式与任何其他存储项相同,并消耗相同数量的存储空间。

于 2019-07-26T20:48:18.750 回答