4

When writing:

let events = frame_system::Pallet::<T>::events();

I get the error:

error[E0599]: no function or associated item named `events` found for struct `frame_system::Pallet` in the current scope

and the implementation: https://docs.rs/frame-system/3.0.0/frame_system/pallet/struct.Pallet.html#method.events

Any ideas? TIA

1
  • Welcome to the community! For us to help you, please provide a Minimal, Reproducible Example so we can better understand the context you are trying to implement this code in.
    – Nuke
    Commented Mar 17, 2022 at 15:20

2 Answers 2

4

We have specifically removed access to the Events storage item in frame_system because it could cause the user to read a huge amount of storage, and the events storage is only meant to be read offline.

/// Get the current events deposited by the runtime.
///
/// NOTE: This should only be used in tests. Reading events from the runtime can have a large
/// impact on the PoV size of a block. Users should use alternative and well bounded storage
/// items for any behavior like this.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn events() -> Vec<EventRecord<T::Event, T::Hash>> {
    Self::read_events_no_consensus()
}

You can see in the code this function is disabled unless you are running tests or benchmarks.

Some more context can be found in this PR: https://github.com/paritytech/substrate/pull/9619

Instead, we provide an "explicitly named" function called read_events_no_consensus, which bypasses this protection from the user, and hopes that the user understands what they are doing.

/// Get the current events deposited by the runtime.
///
/// Should only be called if you know what you are doing and outside of the runtime block
/// execution else it can have a large impact on the PoV size of a block.
pub fn read_events_no_consensus() -> Vec<EventRecord<T::Event, T::Hash>> {
    Events::<T>::get()
}

This can be helpful for scenarios like an offchain worker reading into the events, which would be okay since this would not appear as a storage read in the PoV for a parachain.

2

I found out that pub fn events() should only be used in tests, so I'm using pub fn read_events_no_consensus() now. See code below:

    #[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
    #[scale_info(skip_type_params(T))]
    pub struct IndexingData<T: Config> {
        pub key: Vec<u8>, 
        pub value: Vec<EventRecord<<T as frame_system::Config>::Event, <T as frame_system::Config>::Hash>>,
    }

    #[pallet::hooks]
    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
        /// Block finalization
        fn on_finalize(_n: BlockNumberFor<T>) {
            let key = Self::derived_key(frame_system::Pallet::<T>::block_number());
            let events = frame_system::Pallet::<T>::read_events_no_consensus();
            let data = IndexingData::<T> { key: b"submit_events".to_vec(), value: events };

            offchain_index::set(&key, &data.encode());
        }

        fn offchain_worker(block_number: T::BlockNumber) {
            // Reading back the off-chain indexing value. This is exactly the same as reading from
            // ocw local storage.
            let key = Self::derived_key(block_number);
            let storage_ref = StorageValueRef::persistent(&key);
            
            if let Ok(Some(data)) = storage_ref.get::<IndexingData<T>>() {
            log::info!("local storage data: {:?}, {:?}", sp_std::str::from_utf8(&data.key).unwrap_or("error"), data.value);
            } else {
                log::info!("Error reading from local storage.");
            }
        }
    }
4
  • 2
    Can you explain why you are calling this function outside of tests? this is really not the right thing to do in general, and I hope you see the comments above the function you are using. "Should only be called if you know what you are doing and outside of the runtime block execution else it can have a large impact on the PoV size of a block."
    – Shawn Tabrizi
    Commented Mar 17, 2022 at 15:54
  • 3
    Thanks @ShawnTabrizi. I'm trying to replicate Tomasz Drwięga off-chain indexing example. I want to index every event to the local-storage and then use a OCW to read the indexed-data and RPC it into a neo4j database. Commented Mar 17, 2022 at 15:59
  • okay, this sounds reasonable. good luck!
    – Shawn Tabrizi
    Commented Mar 17, 2022 at 16:43
  • Thank you @ShawnTabrizi. I'll keep you in the loop. Commented Mar 17, 2022 at 16:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.