简体   繁体   中英

What is the cost of event storage in substrate?

While implementing my chain logic I was wondering whether to use events at all since they might cost the node extra storage for the event logs. What is the actual storage cost involved here? Do the logs get purged automatically at some point?

Runtime events are handled by the System module . Within your own module, you normally implement the default deposit_event function:

From the in-code documentation:

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 .

If you look at the System module code , you will find that ultimately a helper function is called which stores the event:

/// 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) { ... }

This function modifies three storage items which you can find in the decl_storage for the System module:

/// 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)>;

The final part of the event story can be found in the initialize function in the System module, where all three of these items are "cleaned up":

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

This initialize function is called in the Executive module at the beginning of every block, before on_initialize is called for any module:

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);
}

In conclusion, the cost of adding a single Event in the runtime is:

  • Running the deposit_event_indexed function.
  • Adding a new item to two vectors in runtime storage.
  • ... which are cleaned up at the beginning of the next block so the storage cost is not compounding.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM