Substrate 中事件存储的成本是多少?
What is the cost of event storage in substrate?
在实现我的链逻辑时,我想知道是否完全使用事件,因为它们可能会花费节点额外的事件日志存储空间。这里涉及的实际存储成本是多少?日志会在某个时候自动清除吗?
事件的创建方式与任何其他存储项目相同,并根据发出的内部数据的类型消耗相同的存储量。
运行时事件由 System module 处理。在您自己的模块中,您通常会实现默认的 deposit_event
函数:
来自代码内文档:
deposit_event
: Helper function for depositing an event. The default behavior is to call deposit_event
from the System module. However, you can write your own implementation for events in your runtime. To use the default behavior, add fn deposit_event<T>() = default;
to your Module
.
如果你查看 System module code,你会发现最终调用了一个辅助函数来存储事件:
/// 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
函数中找到,其中所有这三个项目都是 "cleaned up":
pub fn initialize( ... ) {
...
<Events<T>>::kill();
EventCount::kill();
<EventTopics<T>>::remove_prefix(&());
}
此 initialize
函数在每个块的开头在 Executive module 中调用,在为任何模块调用 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);
}
综上所述,在运行时添加单个事件的成本是:
- 运行
deposit_event_indexed
函数。
- 正在将新项目添加到运行时存储中的两个向量。
- ...在下一个块的开头清理,因此存储成本不会增加。
在实现我的链逻辑时,我想知道是否完全使用事件,因为它们可能会花费节点额外的事件日志存储空间。这里涉及的实际存储成本是多少?日志会在某个时候自动清除吗?
事件的创建方式与任何其他存储项目相同,并根据发出的内部数据的类型消耗相同的存储量。
运行时事件由 System module 处理。在您自己的模块中,您通常会实现默认的 deposit_event
函数:
来自代码内文档:
deposit_event
: Helper function for depositing an event. The default behavior is to calldeposit_event
from the System module. However, you can write your own implementation for events in your runtime. To use the default behavior, addfn deposit_event<T>() = default;
to yourModule
.
如果你查看 System module code,你会发现最终调用了一个辅助函数来存储事件:
/// 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
函数中找到,其中所有这三个项目都是 "cleaned up":
pub fn initialize( ... ) {
...
<Events<T>>::kill();
EventCount::kill();
<EventTopics<T>>::remove_prefix(&());
}
此 initialize
函数在每个块的开头在 Executive module 中调用,在为任何模块调用 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);
}
综上所述,在运行时添加单个事件的成本是:
- 运行
deposit_event_indexed
函数。 - 正在将新项目添加到运行时存储中的两个向量。
- ...在下一个块的开头清理,因此存储成本不会增加。